home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / programer2 / sdls / Manual_manText < prev    next >
Encoding:
Text File  |  1995-05-18  |  121.2 KB  |  3,209 lines

  1.                   ______   ________                   ______
  2.                  /          |      \     |           /
  3.                 (           |       \    |          (
  4.                  \______    |        \   |           \______
  5.                         \   |         )  |                  \
  6.                          )  |        /   |                   )
  7.                 ________/  _|_______/    |________  ________/
  8.  
  9.   T h e   S t r a y l i g h t   D y n a m i c   L i n k i n g   S y s t e m
  10.  
  11.  
  12.                                   Straylight
  13.  
  14.                   16 Portland Street, Royal Leamington Spa,
  15.                             Warwickshire, CV32 5HE
  16.  
  17.                     Telephone and facsimile: 01926 452639
  18.                     Email:  strylght@strylght.demon.co.uk
  19.  
  20. _____________________________________________________________________________
  21.  
  22.  
  23.                          Some notes on this document
  24.  
  25.  
  26.         This text file should contain the complete text of the SDLS manual.
  27.         It has been generated by Impression, and formatted by hand.
  28.         Therefore, there may be come accidental omissions, and the formatting
  29.         may differ from the original document.
  30.  
  31.         This text file should therefore be viewed as a `convenience'.  The
  32.         definitive version of the documentation is the Impression Publisher
  33.         document.
  34.  
  35.         In addition, it is not possible to include all of the figures and
  36.         tables in a text form.  These are supplied in Draw and ArtWorks
  37.         format.  To view the ArtWorks files, use Computer Concepts' AWViewer
  38.         application, available on hensa, and from many other sources.
  39.  
  40.         Note that listings are not formatted, and may extend past the end
  41.         of a line.  This is so that you can extract the listings and use
  42.         them in your own code directly.
  43.  
  44. _____________________________________________________________________________
  45.  
  46.  
  47.         © 1995 Straylight.  All rights reserved.
  48.  
  49.         This documentation refers to the Straylight Dynamic Linking System
  50.         version 1.00.
  51.  
  52.         There is no warranty for the program, to the extent permitted by
  53.         applicable law.  Except when  otherwise stated in writing the
  54.         copyright holders and/or other parties provide the program ‘as  is’
  55.         without warranty of any kind, either expressed or implied, including,
  56.         but not limited to, the  implied warranties of merchantability and
  57.         fitness for a particular purpose.  The entire risk as to  the quality
  58.         and performance of the program is with you.  Should the program prove
  59.         defective,  you assume the cost of all necessary servicing, repair or
  60.         correction.
  61.  
  62.         The product described in this documentation is the subject of
  63.         continual development and,  while all efforts are taken to ensure
  64.         that the information given is correct, Straylight cannot  accept any
  65.         liability for loss or damage resulting from the use or misuse of this
  66.         product.
  67.  
  68. Trademarks
  69.  
  70.         Acorn, Archimedes and RISC PC are trademarks of Acorn Computers Ltd.
  71.         ARM is a trademark of Advanced RISC Machines Ltd.
  72.         All other trademarks acknowledged.
  73.  
  74. _____________________________________________________________________________
  75.  
  76.  
  77.                                  Introduction
  78.  
  79.  
  80. An introduction to dynamic linking
  81.  
  82.         Many current RISC OS applications use common libraries such as
  83.         RISC_OSLib or DeskLib.  Such libraries are usually quite large, and
  84.         currently each application using the library contains its own copy of
  85.         the  library code.  This is wasteful of both disk space and, much
  86.         more  importantly, memory space. Figure 1.1 shows this
  87.         diagrammatically.
  88.  
  89.                 Figure 1.1: Applications using common libraries
  90.  
  91.         This document describes a method for libraries to be held as separate
  92.         files, allowing multiple applications to use a single copy of the
  93.         library  held in memory.  In order for this system to work, an
  94.         application must be  able to find the routines it requires at
  95.         run-time.  This process is called  ‘dynamic linking’, by analogy with
  96.         normal ‘static’ linking.  Figure 1.2  shows this improvement applied
  97.         to the situation shown in Figure 1.1.
  98.  
  99.                 Figure 1.2: Applications using a shared library
  100.  
  101.         With dynamic linking, our view of what constitutes an application
  102.         must  change.  We must now consider an application to consist of:
  103.  
  104.         •  One main program, which contains the main application code.
  105.            This  main program will normally be contained within an absolute
  106.            image,  although it is also possible for it to be kept in a
  107.            RISC OS relocatable  module.
  108.  
  109.         •  Any number of Dynamic Link Libraries, which may be shared with
  110.            other applications.
  111.  
  112.         For the Straylight Dynamic Linking System (SDLS) to work, a small
  113.         module called the DLLManager is provided.
  114.  
  115.  
  116. Languages supported by the system
  117.  
  118.         The Straylight Dynamic Linking System is designed to support compiled
  119.         languages which conform to the APCS-R calling standard.  This
  120.         includes  most C compilers available for Acorn RISC machines, and
  121.         Acorn’s DDE  Pascal implementation.  It also allows creation of DLLs
  122.         written in  assembler, using any procedure call standard, although in
  123.         this case much  more work is required to implement DLLs.
  124.  
  125.  
  126. Who can use SDLS?
  127.  
  128.         Straylight have decided to make SDLS ‘freeware’.  It remains at all
  129.         times  Copyright © 1995 Straylight; however:
  130.  
  131.         •  Applications using shared or extension DLLs may be distributed
  132.            with  the DLLManager module and !DLLs resource as required.
  133.  
  134.         •  Development kits for shared DLLs may be distributed with parts of
  135.            this package as required.
  136.  
  137.         The above applies to all software products whether or not they are
  138.         commercial.  No charge may be made for any part of SDLS specifically,
  139.         and none of the code or documentation may be altered in any way. You
  140.         may use parts of this documentation within your own manuals for
  141.         shared libraries or applications if you wish.
  142.  
  143.         All products distributed with SDLS or any parts thereof must state in
  144.         the  main documentation such parts are copyright © 1995 Straylight.
  145.  
  146.  
  147. About this manual
  148.  
  149.         This document divided into two parts: a user guide and a reference
  150.         manual.  The user guide gives an overview of the main concepts
  151.         required  to use SDLS.  Further details may be found in the reference
  152.         manual.
  153.  
  154.         The Straylight Dynamic Linking System can be used at two different
  155.         levels: the development of client applications that use existing
  156.         DLLs, and  the creation of new Dynamic Link Libraries.  Both of these
  157.         processes are  dealt with individually in the user guide.
  158.  
  159.         It isn’t necessary to learn how to create your own DLLs if you’re
  160.         only  going to be using existing libraries, although it may give some
  161.         additional  insight into how the system works.  It is necessary to be
  162.         familiar with  both sections if you will be developing DLLs yourself.
  163.  
  164.  
  165. Terminology
  166.  
  167.         The following terms are used throughout this document:
  168.  
  169.         Dynamic Link Library    A collection of routines, usually with a
  170.                                 common  purpose, which may be shared by any
  171.                                 number of  applications running at the same
  172.                                 time.  ‘Dynamic Link Library’ is often
  173.                                 abbreviated as  ‘DLL’.
  174.  
  175.         Client application      An application which makes use of a Dynamic
  176.                                 Link Library.
  177.  
  178.         External procedure call A call from a client application to a DLL,
  179.                                 from a  DLL to a client application, or from
  180.                                 one DLL to  another.
  181.  
  182.  
  183. Package contents
  184.  
  185.         The Straylight Dynamic Linking System consists of several parts:
  186.  
  187.         •  A !DLLs shared resource, which will contain Dynamic Link
  188.            Libraries,  and allow applications to locate them when required.
  189.  
  190.         •  The !DLLMerge application, which allows users to update their
  191.            !DLLs  resource as part of the installation of a new application.
  192.  
  193.         •  A DLLLib library, which provides support for the dynamic linking
  194.            system.
  195.  
  196.         •  The cdll tool, which generates AOF (Acorn Object Format) files
  197.            useful  in constructing DLLs and client applications.
  198.  
  199.         •  A Tutorials directory, which contains example programs used to
  200.            demonstrate the use of the system.
  201.  
  202. _____________________________________________________________________________
  203.  
  204.  
  205.                    P A R T   I :   U S E R ' S   G U I D E
  206.  
  207. _____________________________________________________________________________
  208.  
  209.  
  210.                              !DLLs and !DLLMerge
  211.  
  212.  
  213.         The Straylight Dynamic Linking System provides a shared resource
  214.         called  !DLLs.  It collects together DLLs and allows client
  215.         applications to easily  locate the ones that they require.  This is
  216.         very similar to the way the  standard !System resource allows
  217.         applications to locate the relocatable  modules that they need.
  218.  
  219.         It is normal to keep the !DLLs and !System resources together.  If
  220.         you have  a Risc PC, you will find the !System resource in the
  221.         directory  $.!Boot.Resources.
  222.  
  223.         The !DLLs resource sets up two system variables:
  224.  
  225.         •  DLL$Dir is the full path name of the !DLLs resource.
  226.  
  227.         •  DLL$Path is a path variable allowing access to all currently
  228.            available  shared DLLs.
  229.  
  230.         Inside the !DLLs resource folder are the following files:
  231.  
  232.         •  !Boot and !Run − set up the system variables properly.
  233.  
  234.         •  DLLManager − the DLLManager module.  It is placed here so that
  235.            client  applications can find it easily.
  236.  
  237.         •  A few small utility programs which are used to set up the system
  238.            variables.
  239.  
  240.         •  A number of subdirectories containing DLLs.
  241.  
  242.         The DLLMerge application is aimed at simplifying the process of
  243.         installing applications which require DLLs.  It works in a
  244.         more-or-less  identical way to Acorn’s SysMerge utility.  To use it,
  245.         double click on the  !DLLMerge icon, and drag your master DLLs
  246.         resource folder to the main  window, followed by the DLLs folder on
  247.         the distribution disk.  DLLMerge  then updates the master DLLs
  248.         resource from the copy on the distribution  disk, and rescans the
  249.         resource folder to update the system variables.
  250.  
  251. _____________________________________________________________________________
  252.  
  253.  
  254.                              Using existing DLLs
  255.  
  256.  
  257. Introduction
  258.  
  259.         This chapter will describe how to write client applications which use
  260.         one  or more DLLs in the most common way.  If a library has unusual
  261.         requirements, they will be specified in that library’s documentation.
  262.         In general, using a Dynamic Link Library is very similar to using the
  263.         traditional statically linked kind − all you will need to do is link
  264.         with  some different files.
  265.  
  266.         A DLL will always come in two parts: the actual library code, which
  267.         is  held in the !DLLs resource, and a small ‘stub’, which you link
  268.         into your  application.  If you’re using more than one DLL, you will
  269.         usually just link  with the stubs for each one.  The stub contains
  270.         information which enables  the DLLManager module to load and prepare
  271.         the DLL for use.
  272.  
  273.  
  274. Ensuring library versions
  275.  
  276.         Your application will need to ensure that sufficiently recent
  277.         versions of all  the libraries that it needs are available before it
  278.         starts up.  You can do this  in the application’s !Run file using the
  279.         *command *DLLEnsure as follows:
  280.  
  281.                 DLLEnsure <library name> <version>
  282.  
  283.         You will be told the library’s name and version number in the
  284.         library’s  documentation.
  285.  
  286.  
  287. Client applications written in C
  288.  
  289.         If your application makes use of the Shared C Library, then your link
  290.         step  will need to be modified slightly.  In order to correctly load
  291.         the libraries  your application needs, you will need to link with the
  292.         DLLLib library  supplied with the SDLS distribution.  Also, instead
  293.         of linking with the  standard ‘stubs’, you will need to link with an
  294.         alternative Shared C  Library stub, as follows:
  295.  
  296.         •  For a normal application, use ‘astubs’.
  297.  
  298.         •  For a relocatable module, use ‘mstubs’.
  299.  
  300.         These replacement stubs are compatible with those supplied with Acorn
  301.         C Releases 3 and 4.  However, the stubs supplied with C Release 5
  302.         contain  the new routines _swi and _swix.  If your application makes
  303.         use of these  routines, you have two choices:  either you can use the
  304.         stubs described  above, and also link with the file ‘swiv’ provided
  305.         in the distribution, or  you can use the asstubs or msstubs versions
  306.         (note the additional ‘s’).  The  latter alternative will use the
  307.         routines contained in the Shared C Library,  which saves memory, but
  308.         will prevent your program working under  RISC OS 2.  Also, the
  309.         versions of these routines in the Shared C Library  contain a small
  310.         bug which is not present in the swiv program in this  distribution.
  311.         For these reasons, we recommend that you do not use the  versions of
  312.         these routines in the Shared C Library.
  313.  
  314.         We suggest that you add the DLLLib directory to your standard library
  315.         path (which will normally be C$Path).  This will allow you to specify
  316.         the  object and header files within the directory easily from all of
  317.         your project  directories.  In the examples, we will assume that you
  318.         have done this.
  319.  
  320.  
  321. A brief tutorial
  322.  
  323.         In the directory Tutorial.ClicntEx, there is an example of a very
  324.         simple  client application written in C.  You don’t actually need a C
  325.         compiler,  since we’ve already compiled the source code for the
  326.         client.  You will  however need a linker; either Acorn’s link or the
  327.         freely available drlink is  recommended for this purpose.  This
  328.         section will show you how to create  the actual application image.
  329.  
  330.         We have not supplied a makefile for this example, because we feel
  331.         that it  will be more instructive to perform the operation manually.
  332.  
  333.         The example client requires the DLLExample DLL which is already in
  334.         the  !DLLs resource.  The header file h.dllExample describes the
  335.         functions this  very simple library offers.  The DLL’s stub is
  336.         contained in o.dllExample.
  337.  
  338.         To build the client application, all you need to do is:
  339.  
  340.         1.  Make Tutorial.ClientEx your current directory.
  341.  
  342.         2.  Perform the following command:
  343.  
  344.               link o.clientEx o.dllExample c:o.dllLib c:o.astubs -o ClientEx
  345.  
  346.         (We’ve used Acorn’s link here, although you can use drlink in exactly
  347.         the same way.)
  348.  
  349.         The application is now complete.  If you just run the command
  350.         ClientEx,  a greeting and the current time and date should be printed
  351.         on your  screen.
  352.  
  353.         Note that if you want to compile the source code (clientEx.c), you do
  354.         this  in the usual way.
  355.  
  356.     Complications
  357.  
  358.         Usually, creating your client application is as simple as explained
  359.         above.   However, a lot of this simplicity is dependent on the DLLs
  360.         you are using,  and you should watch out for some pitfalls. In order
  361.         for the DLLManager to keep track of which application is  currently
  362.         calling DLL routines, it makes use of the time at which the
  363.         application was started.  Unfortunately, some operating system calls
  364.         alter  this time, and so you must ensure that you restore it
  365.         immediately  afterwards.  Essentially, any operating system call
  366.         which allows another  application to run will alter the start time;
  367.         these calls are: Wimp_Poll,  Wimp_PollIdle, OS_CLI and Wimp_StartTask
  368.         (which calls OS_CLI)¹.   There are DLLManager calls which allow you
  369.         to save and restore this time  value, and you can use these to
  370.         ‘protect’ the offending operating system  routines, as follows:
  371.  
  372.         •  In C (using the DLLLib functions):
  373.  
  374.            {
  375.              int save;
  376.              dll_saveHandle(&save);
  377.              /* Do operation that needs 'protection' */
  378.              dll_restoreHandle(&save);
  379.            }
  380.  
  381.         •  In assembler:
  382.  
  383.                 SWI     DLL_SaveHandle          ;Get application handle
  384.                 STMFD   R13!,{R0}               ;Save it on the stack
  385.                 ; Do operation that needs 'protection'
  386.                 LDMFD   R13!,{R0}               ;Get application handle back
  387.                 SWI     DLL_RestoreHandle       ;Set it as the current one
  388.  
  389.         DLLlib already includes functions for handling OS_CLI and
  390.         Wimp_StartTask ‘safely’.  A good WIMP library will provide a way of
  391.         calling Wimp_Poll and Wimp_PollIdle.
  392.  
  393.         The other problem, which only applies if your program is written in C
  394.         or  a similar language, is that the DLLManager needs to be able to
  395.         keep track  of which part of an application is currently executing.
  396.         Normally, this will  happen automatically.  Problems only occur when
  397.         your program does not  follow normal function call and return
  398.         discipline.  This will usually  happen as a result of a call to the
  399.         standard C longjmp function.  The  problems occus because the
  400.         DLLManager needs to maintain a stack  containing information about
  401.         external procedure calls, and a longjmp call  causes the DLLManager’s
  402.         stack pointer to become out of sync.  The  solution is to remember
  403.         the stack pointer when you call setjmp and  restore it again when
  404.         setjmp returns, as follows:
  405.  
  406.         {
  407.           int stackptr;
  408.           jmp_buf j;
  409.  
  410.           dll_readStackPtr(&stackptr);
  411.           if (setjmp(j))
  412.           {
  413.  
  414.             /* --- Someone longjmped here --- */
  415.  
  416.             dll_setStackPtr(stackptr);
  417.             /* Other handling */
  418.           }
  419.         }
  420.  
  421.     Module clients written in C
  422.  
  423.         Special care must be taken if your client application is actually a
  424.         relocatable module.  If your module passes function pointers to a
  425.         DLL, then you  should read the sections on The cdll tool and
  426.         Complications in the next  chapter before reading any further.
  427.  
  428.         Due to the way the DLLManager works, a module client must contain
  429.         entry veneers for each function which may be called from a DLL
  430.         through  a function pointer.  These are created by cdll − you must
  431.         create a  definition file containing only the ‘extEntry’ and
  432.         ‘objects’ sections.  You  can generate an object file containing the
  433.         entry veneers for the functions  named in the ‘extEntry’ section by
  434.         using the command:
  435.  
  436.                 cdll -def <defn file> -ext <output file>
  437.  
  438.         Note that the entry veneer for a function foobar will be
  439.         _extEntry_foobar.
  440.  
  441. _____________________________________________________________________________
  442.  
  443.  
  444.                        Creating Dynamic Link Libraries
  445.  
  446.  
  447. Introduction
  448.  
  449.         This part of the manual will explain how you can write your own
  450.         Dynamic Link Libraries.  It is expected that you have already read
  451.         the  chapter Using existing DLLs.
  452.  
  453.         Creating DLLs can be a considerably more complex task than writing
  454.         client applications − this doesn’t mean that all libraries will be
  455.         hard to  write, but the relative ease of writing clients is mainly
  456.         due to the effort  put in by the library developers.
  457.  
  458.         Whether you are writing an entirely new Dynamic Link Library, or
  459.         converting an existing static library into a DLL, it is vital that
  460.         you have a  reasonable understanding of the concepts introduced here.
  461.         Such  familiarity will make your task as a DLL developer much
  462.         simpler.
  463.  
  464.  
  465. Structure of a DLL
  466.  
  467.         Conceptually, a Dynamic Link Library consists of two parts: the code
  468.         part,  which contains all the routines that client applications will
  469.         use, and the  header, which contains information used by the
  470.         DLLManager module. Each routine that a DLL exports to its clients has
  471.         an entry point − this is  simply the start address of the routine in
  472.         memory.  In order to use a  routine, the client application must find
  473.         its entry point; we will discuss  how this is done below.
  474.  
  475.         The code part of a DLL is usually built from a number of AOF object
  476.         files  or statically linked libraries.  These are generated from your
  477.         library’s  source code in the same way as for a statically linked
  478.         library. Naming of DLLs and entry points
  479.  
  480.         The DLLManager keeps track of Dynamic Link Libraries by use of their
  481.         names.  For this reason, each DLL must have a unique name.  If you
  482.         are  planning to release a DLL, you should read the chapter
  483.         Registering  names.  DLL names may be at most 10 characters long, and
  484.         must be the  same as its leafname.
  485.  
  486.         Each entry point must also be given a name.  Entry point names only
  487.         have to be unique within a particular DLL.  However, you should be
  488.         aware that the linker will not allow multiple definitions of
  489.         identifiers.   This rarely occurs in practice with well-chosen names
  490.         − we recommend  that you group routines with a common purpose by
  491.         giving them a  suitable common prefix.  For example, in a library
  492.         offering WIMP  services, all the routines concerned with dialogue box
  493.         management might  begin with the prefix ‘dbox_’.  Since a client is
  494.         unlikely to use more than  one such library, this naming strategy
  495.         should not cause too many  problems.
  496.  
  497.  
  498. ‘Foreverness’ and version control
  499.  
  500.         One of the main difficulties in designing a Dynamic Link Library is
  501.         version control.  A version of a DLL must try to remain compatible
  502.         with  clients which were written for an earlier version of the
  503.         library.  This  means that the routines provided by your library must
  504.         keep the same  external interfaces, or ones which are compatible with
  505.         earlier releases.   This concept is termed ‘foreverness’.
  506.  
  507.         A full discussion of foreverness is beyond the scope of this
  508.         document.   However, when designing a DLL you should attempt to
  509.         ensure that you  can easily extend your interfaces in a compatible
  510.         way, for example by  making use of reserved fields and flags.
  511.         RISC OS itself contains many  good examples of this sort of design.
  512.  
  513.         The DLLManager goes some way to help you with the problems of version
  514.         control.  You must include a version number in the header of a DLL.
  515.         This  is checked against the version number requested by the client.
  516.         An error is  reported if there is no sufficiently recent version of
  517.         your library available. A complete discussion of version handling is
  518.         given in the reference part  of this document.
  519.  
  520.  
  521. The cdll tool
  522.  
  523.         The DLL header and stubs files have a fairly complex format, and
  524.         building these by hand is difficult and prone to errors.  The cdll
  525.         tool is a  small program which will generate these and other dynamic
  526.         linking- related data structures from simple textual descriptions.  A
  527.         full descrip tion of cdll is given in the chapter The cdll tool in
  528.         the reference section.   Here, we shall only discuss the parts
  529.         relevant to the creation of Dynamic  Link Libraries.
  530.  
  531.     Definition files
  532.  
  533.         You describe your DLL to cdll by means of a definition file, which
  534.         contains  all the information needed to create the DLL’s header and
  535.         stub.  An  annotated example of a definition file for a simple DLL is
  536.         shown in  figure 4.1.
  537.  
  538.         If you are converting an existing statically linked library into a
  539.         DLL, then  the creation of a definition file by hand would be very
  540.         time-consuming.
  541.  
  542.         To help solve this problem, cdll can create a skeleton definition
  543.         file based  on a number of given object files and libraries.  You
  544.         will need to modify  the resulting file by hand before you can use
  545.         it, although cdll will have  done the bulk of the work for you.  To
  546.         do this, use the command
  547.  
  548.                 cdll -def <output file> -obj <object/library files>
  549.  
  550.         If you are creating a Dynamic Link Library from scratch, or you have
  551.         a  definition file prepared using the above method, you will need to
  552.         maintain the file by hand as you add new routines to your library.
  553.         This is  unlikely to be difficult.
  554.  
  555.     Creating DLL headers and stubs
  556.  
  557.         Once you have a definition file, you can create the DLL’s header and
  558.         stubs as AOF (object) files using the command:
  559.  
  560.                 cdll -def <defn file> -stub <stub name> -hdr <header name>
  561.  
  562.         The stub is ready for inclusion in client applications, as described
  563.         in the  previous chapter.  The header can be used to create the
  564.         finished Dynamic  Link Library as explained below.
  565.  
  566. Linking
  567.  
  568.         Once you have the object files for your DLL’s code and header parts,
  569.         you  can link them together to form the finished DLL:
  570.  
  571.                 link -rmf <object files> -o <dll filename>
  572.  
  573.         It is important to notice that the linker’s ‘-rmf’ option is used −
  574.         this will  automatically create the code necessary to relocate the
  575.         DLL when it is  loaded.  The freely available drlink program also has
  576.         this option. The DLL file created by link using the above command has
  577.         its filetype set  to be a relocatable module.  You will probably want
  578.         to change this to be  Data (type &FFD).
  579.  
  580. Writing DLLs in C
  581.  
  582.         There are some special considerations you must bear in mind when
  583.         writing a DLL in C or a similar language.  The compiler options
  584.         described  here are applicable to the Acorn C and Pascal compilers.
  585.         Other compilers  may include equivalent features − check your
  586.         compiler’s documentation  for details.
  587.  
  588.     Compiling
  589.  
  590.         When you compile code for use in a Dynamic Link Library, you must use
  591.         the compiler’s ‘-zM’ option, which requests the compiler to create
  592.         code  suitable for a relocatable module.  Code compiled in this way
  593.         has  properties which make it possible for it be used in DLLs.  If
  594.         your compiler  does not support an equivalent option, you will not be
  595.         able to create  DLLs with it.
  596.  
  597.         The SDLS package contains some replacement C library header files
  598.         (ctype.h, errno.h, math.h and stdio.h) as part of the DLLLib, and you
  599.         must ensure that these are included by your source files, instead of
  600.         the  standard ones.  To activate the modifications made to these
  601.         header files,  you must define the macro _DLL (e.g. using the
  602.         compiler option ’-d_DLL‘) −  this must only be done when compiling
  603.         code for a DLL; do not define this  symbol when creating client
  604.         applications.  Assuming that the replacement  header files are
  605.         contained within the directory c:dlllib.h, you can  ensure that they
  606.         are included correctly by using the option  ’Jc:dlllib.,:mem‘.  This
  607.         overrides the default search mechanism, which  will find copies of
  608.         the header files embedded in the compiler, and instead  locates the
  609.         SDLS versions first.  If your compiler does not support this  type of
  610.         operation, you must use explicit paths in your source code (e.g.
  611.         #include "c:dlllib.h.stdio").
  612.  
  613.         As an example, to compile the file c.hellow, use the command
  614.  
  615.                 cc -d_DLL -Jc:dlllib.,:mem -zM -c hellow.c -o hellow.o
  616.  
  617.         The compiler commands can become very complicated − we therefore
  618.         recommend that you use a makefile to manage creation of DLLs.
  619.  
  620.     Linking
  621.  
  622.         When you are linking your object files to create the final Dynamic
  623.         Link  Library, you must also link with the DLLLib library and the
  624.         dstubs Shared  C Library stubs.  For example
  625.  
  626.                 link -rmf <object files> c:dlllib.o.dlllib c:dlllib.o.dstubs
  627.                         -o <dll filename>
  628.  
  629.         Note that the dstubs do not include the new Shared C Library entry
  630.         points  _swi and _swix − if you require these, you should link with
  631.         the supplied  swiv object file as described in the previous chapter.
  632.  
  633.     Debugging
  634.  
  635.         Unfortunately, it is not possible to include debugging information in
  636.         a  DLL.  If you wish to debug your library, it is wise to allow both
  637.         a  statically and dynamically linked version to be built from the
  638.         same source  code.  You can use the preprocessor macro _DLL described
  639.         above to  conditionally compile the appropriate code for both
  640.         versions.
  641.  
  642.     Complications
  643.  
  644.         All the complications described in the previous chapter, regarding
  645.         Wimp_Poll etc. and longjmp also apply to DLLs.  However, there is a
  646.         further complication if you use function pointers.
  647.  
  648.         The DLLManager must perform some setting-up operations whenever one
  649.         of your DLL’s entry points is called.  This happens automatically
  650.         most of  the time.  However, you must be careful when returning
  651.         pointers to  functions contained within your library to the client
  652.         application. A normal call  to one of your routines is actually
  653.         routed through a small  piece of code called an entry veneer.  This
  654.         allows the DLLManager to  perform its setting up before it passes
  655.         control to the actual routine.  If the  client application were to
  656.         call one of your routines directly through a  function pointer, the
  657.         DLLManager would not be able to set up the  environment correctly for
  658.         the routine, and your program would fail.  The  solution is to ensure
  659.         that you always return the address of the routine’s  entry veneer,
  660.         rather than its actual address.
  661.  
  662.         Each entry veneer is given a name based on its routine’s name − for
  663.         example, the entry veneer for the routine dbox_create would be called
  664.         _dllEntry_dbox_create.  If you want to set up a function pointer with
  665.         the  address of a routine which may be returned to the client
  666.         application, you  must instead use the name of the entry veneer.
  667.  
  668.         Note that if a function pointer will not be used outside of your DLL,
  669.         you  need not use the address of the veneer.  However, no harm will
  670.         be done if  you do.
  671.  
  672.         You may have routines which you do not want to export to the client
  673.         application by name, but you may want to be able to return function
  674.         pointers to them.  You can do this by naming them in your cdll
  675.         definition  file in a section labelled extEntry.  This section is
  676.         otherwise the same as  the exports section already discussed.
  677.  
  678.         To assist in the management of source code being used in both
  679.         statically  and dynamically linked libraries, the DLLLib library
  680.         contains a header file  dll.h which defines the following macros:
  681.  
  682.         _dll_static     When compiling a statically linked library, this
  683.                         macro  expands to ‘static’.  When compiling a DLL, it
  684.                         does  nothing.  This is useful if you are returning a
  685.                         function  pointer to a function, but do not want it
  686.                         visible to the client.
  687.  
  688.         _dllEntry(x)    When compiling a statically linked library, this
  689.                         macro  expands to just ‘x‘.  When compiling a DLL, it
  690.                         expands to  ‘_dllEntry_x’.
  691.  
  692. Writing DLLs in assembler
  693.  
  694.         This section will describe how to write a Dynamic Link Library which
  695.         does not conform to the APCS protocols.  If you are writing a DLL in
  696.         assembler for use with APCS-conforming clients then the previous
  697.         section will be more applicable to you.
  698.  
  699.         If you are writing code which does not conform to APCS, you will not
  700.         be  able to take advantage of a lot of the support offered by the
  701.         DLLManager.   However, by doing this, you will be able to overcome
  702.         the restrictions  imposed by the DLLManager’s APCS support (for
  703.         example, you cannot  implement coroutines using the standard support
  704.         functions because of  the requirement for strict call-return
  705.         discipline).
  706.  
  707.     Re-entrancy
  708.  
  709.         The foregoing discussion of dynamic linking has glossed over one of
  710.         the  important properties which dynamically linked code must have −
  711.         it must  be able to maintain a separate state for each of its client
  712.         applications.  It  will help to define some terminology: we say that
  713.         a routine is threaded  after it has been called, but before it
  714.         returns to its caller.  Since RISC OS is  a multitasking environment,
  715.         it is conceivable that a routine in a DLL is  threaded by more than
  716.         one client simultaneously.  Such a routine must be  able to correctly
  717.         locate its state information for each client.  Code that can  cope
  718.         with this is said to be re-entrant.
  719.  
  720.         A routine will usually keep temporary data in or relative to
  721.         registers.   Since each client will see a different set of register
  722.         values, this causes no  problems for re-entrancy.  The difficulty
  723.         comes in trying to maintain the  library’s persistent state.
  724.  
  725.         The recommended approach is to collect all your library’s data areas
  726.         together, and keep their location in or relative to a register.  This
  727.         location  should be set up when the library is initialised by a
  728.         client.  The client can  then pass this address to the library when
  729.         it makes external calls.
  730.  
  731.     Important points to note
  732.  
  733.         Since you are not using the DLLManager’s APCS support facilities, you
  734.         will not require the entry veneers for your routines.  These entry
  735.         veneers  are normally generated automatically by cdll.  To prevent
  736.         cdll from  generating these veneers, you must put the keyword
  737.         ‘nonAPCS’ in your  DLL definition file, outside of any sections
  738.         enclosed in braces.
  739.  
  740.         You should note that the automatic loading of DLLs is a property of
  741.         the  SDLS Shared C Library stubs.  You should provide a means for
  742.         client  applications to find their DLLs if they are not using these
  743.         stubs.  Details  on how this automatic startup works can be found in
  744.         the reference  section.
  745.  
  746. _____________________________________________________________________________
  747.  
  748.  
  749.                                 Extension DLLs
  750.  
  751.  
  752. Introduction
  753.  
  754.         As well as providing facilities for the implementation of shared
  755.         libraries,  the Straylight Dynamic Linking System provides a method
  756.         by which  applications may easily load extension code if it is
  757.         required.  Such  extensions are called extension DLLs and might
  758.         provide further facilities  which may not always be required.  In
  759.         addition, you might publish the  interface to your application and
  760.         allow extensions to it to be written by  third parties.
  761.  
  762.         A DLL containing a shared library is loaded into the RMA, where it
  763.         can  be accessed by all its clients.  In contrast, extension DLLs are
  764.         loaded into  its client’s application space − it is therefore local
  765.         to that application. This chapter will describe how to write both
  766.         extension DLLs and  applications which make use of them.  It is
  767.         expected that the reader is  familiar with the material presented in
  768.         the previous two chapters.
  769.  
  770.  
  771. Application entry points
  772.  
  773.         In contrast to shared DLLs, where the DLL defines its interface to
  774.         clients,  an application making use of extension DLLs will need to
  775.         define an  interface to its libraries.  It does this by declaring
  776.         named entry points, in a  similar way to a shared library.  Extension
  777.         DLLs will find these entry  points and so be able to communicate with
  778.         the application.
  779.  
  780.         You define an application’s entry points by creating a cdll
  781.         definition file,  containing the ‘exports’ and ‘objects’ sections.
  782.         You can then build a  ‘header’ which you link into your client, which
  783.         defines these entry points  to the DLLManager, and a ‘stub’ which is
  784.         linked into the extension DLLs.  You can build these files using the
  785.         command:
  786.  
  787.                 cdll -app -def <defn file> -hdr <header> -stub <stub>
  788.  
  789.         The DLLLib will automatically register the application’s entry points
  790.         with  the DLLManager module when the application starts up.  If you
  791.         are not  using the APCS support offered by the DLLManager, you should
  792.         see the  description of the SWI DLL_RegisterAppEntryTable in the
  793.         reference  section.
  794.  
  795.  
  796. Creating extension DLLs
  797.  
  798.         Creating an extension DLL is not very different from creating a
  799.         shared  DLL.  The main differences are that you do not create a stub
  800.         for the DLL,  and you will need to link in the application’s stub.
  801.         To create only the  DLL header and not the stub, use the command:
  802.  
  803.                 cdll -def <defn file> -hdr <header file>
  804.  
  805.         (i.e. omit the ‘-stub’ option).
  806.  
  807.  
  808. Loading extension DLLs
  809.  
  810.         An application is responsible for managing the memory used by its
  811.         extension DLLs.  It must find out how large a block is required for
  812.         each  extension and allocate memory appropriately.  It must also
  813.         allocate  memory for the DLL’s data.  This is actually much easier
  814.         than it sounds,  since DLLLib provides a routine which does all of
  815.         this for you.  If you  aren’t using DLLLib, you should consult the
  816.         reference section, which  contains some example code for doing this.
  817.  
  818.         The DLLLib routine, called _dll_loadExtension, will load a file and
  819.         return  a DLL handle, which you can use to reference the DLL in
  820.         future. Once the DLL is loaded, it will remain idle until you call it
  821.         through an  entry point.  It is usual for an extension DLL to provide
  822.         a single entry  point which is called when it is loaded − the name of
  823.         this entry point will  be fixed by the application.  To find this
  824.         entry point, the application will  call the SWI DLL_FindEntry (or the
  825.         DLLLib routine dll_findEntry) with  the DLL handle and the entry
  826.         point’s name.  The entry point can now be  called − the extension can
  827.         then call routines in the application to register  its services.
  828.  
  829. _____________________________________________________________________________
  830.  
  831.  
  832.                               Registering names
  833.  
  834.  
  835. Why bother registering?
  836.  
  837.         Under this system, many things are given names to try to identify
  838.         them.   It makes sense therefore that some measures are taken to make
  839.         sure the  names are unique.  We’ve chosen to use textual names to try
  840.         and give  users as wide a choice as possible, although problems may
  841.         still occur.   Therefore you should register any names you want to
  842.         use with Straylight  to avoid clashes.
  843.  
  844.  
  845. Who needs to register?
  846.  
  847.         Certainly, any commercial software which uses this system ought to
  848.         register any names it requires.   Authors of ‘alternatively
  849.         distributed’ software (e.g. Public Domain,  Freeware, Shareware,
  850.         Careware) should register DLL names too − it  doesn’t take very much
  851.         to register, and it can save a lot of problems if  there’s a clash.
  852.         They don’t have to register client application names,  although we do
  853.         recommend that they do.
  854.  
  855.  
  856. What needs to be registered?
  857.  
  858.         You need to register any of the following names:
  859.  
  860.         Shared DLL names
  861.  
  862.                 Since DLLs are identified by name alone once they’re loaded
  863.                 into memory, names must be unique.  The results of a clash
  864.                 here could be catastrophic.  All shared DLL names must be
  865.                 registered with Straylight.
  866.  
  867.         DLL client names
  868.  
  869.                 Applications are identified by name in various *commands,
  870.                 and user confusion would be reduced considerably if the
  871.                 names were different!
  872.  
  873.                 If your client’s application or module name is registered
  874.                 with  Acorn, then that should be acceptable for use as a DLL
  875.                 client  name.  You should still register in any case.
  876.                 Someone else who  hasn’t registered with Acorn may already
  877.                 have taken your  name.
  878.  
  879.         DLL resource subdirectories
  880.  
  881.                 Shared DLLs are stored in the !DLLs resource folder with one
  882.                 subdirectory for each source of DLLs.  The name of the
  883.                 subdirectory will typically be the name of the company
  884.                 creating the DLLs (e.g. ours is called ‘Straylight’).  In the
  885.                 event  of a directory becoming full (77 DLLs allocated to a
  886.                 single  source), a new name will be allocated.
  887.  
  888.                 ‘Alternatively distributed’ DLLs won’t use this system −
  889.                 there  are simply too many sources.  Instead, the names will
  890.                 be  allocated as ‘Misc_1’, ‘Misc_2’ etc.  You will be given a
  891.                 directory name when you register your shared DLL name. DLL
  892.                 entry point names do not need to be registered, since an
  893.                 entry point  name is always passed with a DLL handle to
  894.                 resolve into an address.   Extension DLL names don’t need to
  895.                 be registered either, since the  DLLManager is only
  896.                 interested in the DLL’s handle in this case.
  897.  
  898.  
  899. How do I register?
  900.  
  901.         You can register in any of the following ways:
  902.  
  903.         •  Telephone or fax: 01926 452639
  904.  
  905.         •  By mail, to:
  906.  
  907.                 Straylight
  908.                 16, Portland Street
  909.                 Royal Leamington Spa
  910.                 Warwickshire
  911.                 CV32 5HE
  912.  
  913.         •  By email, to:
  914.  
  915.                 dlls@strylght.demon.co.uk
  916.  
  917.         We do not charge a fee for registration.
  918.  
  919. _____________________________________________________________________________
  920.  
  921.  
  922.               P A R T   I I :   R E F E R E N C E   M A N U A L
  923.  
  924. _____________________________________________________________________________
  925.  
  926.                              How the system works
  927.  
  928. Introduction
  929.  
  930.         This section describes how the Straylight Dynamic Linking System
  931.         works.   It is not necessary to understand all of this to use SDLS,
  932.         although you  may find it interesting anyway.
  933.  
  934.         It is assumed that the reader is already fairly familiar with ARM
  935.         assembler and the ARM Procedure Call Standard (APCS). This section
  936.         will re-iterate some of the points made in earlier chapters.
  937.         However, it goes into considerably greater depth.
  938.  
  939.  
  940. The basic idea
  941.  
  942.         Sharing code on its own is not difficult − all that is necessary is
  943.         to put the  code in shared memory (e.g. the RMA) and allow clients to
  944.         find it.  The  difficulty lies in maintaining separate areas of data
  945.         for each application  (the DLL’s instance data for the application).
  946.         Fortunately, the Acorn ANSI  C and ISO Pascal compilers provide a
  947.         facility for relocating data  references at run-time: if the -zM
  948.         option is specified on the compiler  command line, data references
  949.         such as
  950.  
  951.                         LDR     a1,dataptr
  952.                         ;
  953.                         ; Some code...
  954.                         ;
  955.  
  956.          dataptr        DCD     data
  957.  
  958.         are replaced by the (slightly) more complex
  959.  
  960.                         LDR     a1,dataptr
  961.                         LDR     ip,[sl,#_Mod$Reloc$Off]
  962.                         ADD     a1,ip,a1
  963.                         ;
  964.                         ; Some code...
  965.                         ;
  966.  
  967.         dataptr         DCD     data
  968.  
  969.         By changing the offset contained at [sl,#_Mod$Reloc$Off], the DLLMana
  970.         ger can make the code reference different areas of data.  Note that
  971.         the  value of _Mod$Reloc$Off is by default −536.
  972.  
  973.         This slight alteration to data referencing code is the only
  974.         difference which  the –zM option makes.
  975.  
  976.         The DLLManager module then keeps a table of these data relocations
  977.         for  each DLL/client pair.  When an external call is made to a DLL,
  978.         control  passes through a small entry veneer called _dll_entry, which
  979.         sets up the  relocation offset correctly, and inserts an exit veneer
  980.         (_dll_exit) to restore  it when the external procedure call returns.
  981.  
  982.  
  983. Handling exceptional control flow
  984.  
  985.         Unfortunately, normal explicit procedure call is not the only way in
  986.         which control is given to functions.  Function pointers must be used
  987.         with  care within DLLs and module clients.  All external calls except
  988.         those to  absolute program images must go through entry and exit
  989.         veneers.  Ways  of ensuring this using the C language are described
  990.         below.
  991.  
  992.         If your program bypasses the normal function return discipline (e.g.
  993.         by  using longjmp) you must ensure that the correct workspace
  994.         relocation is  used.  The DLLManager maintains a stack for each
  995.         client application,  which contains relocations and return addresses.
  996.         If the exit veneer is not  called, the stack becomes invalid.  Hence,
  997.         applications must save the stack  pointer before any return point
  998.         (e.g. setjmp), and restore it if the actual  return point is called
  999.         (by checking the result of setjmp in C).  This is  achieved using the
  1000.         _dll_setjmp and _dll_longjmped functions in DLLLib,  or using SWIs
  1001.         DLL_ReadStackPtr and DLL_SetStackPtr.  C++ exception  handling will
  1002.         not be supported until a way is found to gain control on  entry to a
  1003.         destructor during exception handling.
  1004.  
  1005.  
  1006. Identifying applications
  1007.  
  1008.         For the system to work, it’s necessary for the DLLManager to be able
  1009.         to  identify which application is currently executing, so that it can
  1010.         substitute  the correct workspace relocation.
  1011.  
  1012.         Currently, applications are identified by their start time, as
  1013.         returned by  SWI OS_GetEnv.  This method causes a few problems, since
  1014.         RISC OS  only keeps a record of the start time of the most recent
  1015.         application.   Therefore applications must preserve their times over
  1016.         any system calls  which may start up new applications (e.g.
  1017.         Wimp_Poll, OS_CLI etc.)  This  restriction may be lifted if a better
  1018.         way of identifying the current  application is found.  DLLLib
  1019.         provides functions which replace the most  common offending calls
  1020.         (e.g. system).
  1021.  
  1022.  
  1023. Dynamic linking
  1024.  
  1025.         The actual linking process is very simple.  The DLLManager module has
  1026.         a  SWI DLL_FindEntry which locates a named entry point within a
  1027.         specified  DLL, and returns its address.  Data items are not exported
  1028.         directly, but it  is possible to export functions within the DLL
  1029.         which return the addresses  of data items.
  1030.  
  1031.         Looking up entry points by name, however, is a slow process, and not
  1032.         one that is really desirable for every procedure call.  Therefore,
  1033.         the  DLLManager provides a SWI DLL_FindFromTable which, when given
  1034.         pointers to tables of the appropriate format will load the DLLs
  1035.         specified,  and fill in a branch table with branch instructions to
  1036.         the required entry  points.
  1037.  
  1038.         Since looking up entry points by name is a slow process, and the
  1039.         names  take up a considerable amount of memory, you can assign a
  1040.         small integer  value called an ordinal to each routine.
  1041.  
  1042.         The format of the tables used by DLL_FindFromTable are documented in
  1043.         the reference section.
  1044.  
  1045.  
  1046. How the DLL stubs work
  1047.  
  1048.         A DLL stub object file contains three AREAs, all with attributes CODE
  1049.         and  READONLY, called DLL$$ExternalTable, DLL$$Strings and
  1050.         DLL$$Stubs.   Because the linker joins together AREAs with the same
  1051.         name into one big  AREA and provides symbols giving the start and end
  1052.         addresses of the  AREAs, this allows lots of DLL stubs to be linked
  1053.         together to make an  external DLL table (see the information about
  1054.         SWI DLL_FindFromTable). DLL$$ExternalTable contains a single entry in
  1055.         the external DLL table.   DLL$$Strings contains the name of the DLL
  1056.         to load, and the names of the  entry points required by the client.
  1057.         DLL$$Stubs contains a number of  words, into which branch
  1058.         instructions into the actual DLL may be  inserted at run time.  The
  1059.         initial value of the entries are the ordinals for  the routines to
  1060.         link to, where defined.  Otherwise, they contain the value  &E3A0F000
  1061.         − MOV PC,#0 − which will cause a ‘Branch through zero’  error if the
  1062.         table is used before it is set up properly.
  1063.  
  1064. _____________________________________________________________________________
  1065.  
  1066.  
  1067.                                DLL file format
  1068.  
  1069.  
  1070. Introduction
  1071.  
  1072.         This chapter documents version 1.01 of the DLL file format.
  1073.  
  1074.         DLL files consist of three parts:
  1075.  
  1076.         •  A DLL header which describes all the necessary parts of a DLL to
  1077.            the  DLLManager module
  1078.  
  1079.         •  The actual DLL code
  1080.  
  1081.         •  The initialisation values for the DLL’s data
  1082.  
  1083.         These parts appear in order within the file.
  1084.  
  1085.  
  1086. The DLL header
  1087.  
  1088.         A DLL header contains a fixed size part and a variable size part.
  1089.         The fixed  size part contains pointers to different sections of the
  1090.         variable size part. The fixed size part is the first object in the
  1091.         DLL file.  It contains a number  of 4 byte entries, as follows:
  1092.  
  1093.         Offset  Use
  1094.  
  1095.         0       The 4 byte value &004C4C44, which is the string ‘DLL’
  1096.                 followed by a null byte.  This is used to identify valid  DLL
  1097.                 files.
  1098.  
  1099.         4       The version number of the DLL file format which this
  1100.                 DLL file conforms to, multiplied by 100.  Thus, version  1.01
  1101.                 is represented as 101.
  1102.  
  1103.         8       The address of the DLL’s name.
  1104.  
  1105.         12      The address of the DLL’s author string.  This allows an
  1106.                 author to embed copyright information within a DLL.
  1107.  
  1108.         16      The version number of the DLL, multiplied by 100.
  1109.                 Note that this is distinct from the file format version
  1110.                 number.
  1111.  
  1112.         20      An ARM instruction, normally a branch, which if
  1113.                 excecuted will initialise the DLL, and correctly set up all
  1114.                 the absolute addresses within the DLL.  This routine is
  1115.                 entered in SVC mode with R13 pointing to the super visor
  1116.                 stack and R14 containing a return address and  flags.
  1117.                 Registers R0-R3 and R11 may be corrupted.  It is  expected
  1118.                 that this is in fact the standard linker routine
  1119.                 _Reloc$Code.  If your DLL requires no initialisation, this
  1120.                 instruction may just be MOVS PC,R14.
  1121.  
  1122.         24      The address of the DLL’s Shared C Library stubs branch
  1123.                 table, which is filled in by the DLLManager when the  DLL is
  1124.                 loaded.  If the address is lower than the DLL’s  base
  1125.                 address, then it is assumed that there is no Shared  C
  1126.                 Library entry table.
  1127.  
  1128.         28      The number of entry points offered by the DLL, and
  1129.                 flags.  If bit 31 is set, the entry veneer table (offset 36)
  1130.                 is  replaced by a table of addresses of routines.  This is
  1131.                 used for non-APCS DLLs.
  1132.  
  1133.         32      Pointer to the names of the DLL’s entry points, in order.
  1134.                 The entry point names are each separated by a single  zero
  1135.                 byte, and the last name is followed by a zero byte.   Unnamed
  1136.                 ‘dummy’ entry points, created by gaps in the  ordinals are
  1137.                 indicated by a byte containing the value ‘1’  instead of a
  1138.                 null-terminated string.
  1139.  
  1140.         36      Pointer to the entry veneers table or routine address
  1141.                 table.  There must be at least one table entry for each
  1142.                 named entry point, although there may be more entries  than
  1143.                 named entry points.
  1144.  
  1145.                 An entry veneer is 16 bytes long.  It must set up the
  1146.                 environment for the DLL appropriately and call the  actual
  1147.                 code within the DLL to perform the actions  appropriate for
  1148.                 that entry point.
  1149.  
  1150.                 The routine address table (indicated by bit 31 being set  in
  1151.                 the flags word at offset 28) contains a one word  address of
  1152.                 each routine, instead of a 16 byte entry  veneer.
  1153.  
  1154.                 An ordinal is simply an index into this table − the actual
  1155.                 address of a routine is calculated by multiplying the
  1156.                 ordinal by the size of the table entries (16 for a veneer
  1157.                 table, 4 for an address table).
  1158.  
  1159.         40      Pointer to the base of the external DLL dependency
  1160.                 table.  This table has the same format as that described  for
  1161.                 the SWI DLL_FindFromTable.  If the pointer is equal  to the
  1162.                 pointer at offset 44, then there is no external DLL
  1163.                 dependency table.
  1164.  
  1165.         44      Pointer to the limit of the external DLL dependency
  1166.                 table.
  1167.  
  1168.         48      Pointer to the base of the DLL’s data initialisation
  1169.                 values.  This data is copied to the data area allocated for
  1170.                 the DLL’s instance data to initialise it.
  1171.  
  1172.         52      Pointer to the limit of the DLL’s data initialisation
  1173.                 values.  Note that this may be higher than the DLL’s  actual
  1174.                 limit in memory.
  1175.  
  1176.         56      Pointer to the base of the DLL’s zero-initialised data
  1177.                 area.  This value is relocated to point into the DLL’s
  1178.                 instance data area and used to allow zero-initialisation  of
  1179.                 the data.
  1180.  
  1181.         60      Pointer to the limit of the DLL’s zero-initialised data
  1182.                 area.
  1183.  
  1184.         64      Pointer to the DLL’s application entry point branch
  1185.                 table.  The format of this table and the table pointed to  by
  1186.                 the next word is described with the SWI
  1187.                 DLL_SetExtensionTable.
  1188.  
  1189.         68      Pointer to the names of the application entry points
  1190.                 required in the previous table. The variable size part of the
  1191.                 header contains the entry point names and  branch tables
  1192.                 which are set up on loading the DLL.
  1193.  
  1194. _____________________________________________________________________________
  1195.  
  1196.  
  1197.                                 The cdll tool
  1198.  
  1199.  
  1200. Introduction
  1201.  
  1202.         The cdll tool will create AOF files to help you make both Dynamic
  1203.         Link  Libraries and client applications which use them.  It works
  1204.         from a script  file (called a DLL definition file) which itself may
  1205.         be created by cdll.
  1206.  
  1207.  
  1208. Format of DLL definition files
  1209.  
  1210.         The syntax of the definition files required by cdll is described
  1211.         below:
  1212.  
  1213.         definitionFile ::=      {section}
  1214.  
  1215.         section ::=             nameSection | authorSection |
  1216.                                 versionSection | exportsSection |
  1217.                                 extEntrySection | objectsSection
  1218.  
  1219.         nameSection ::=         ‘name’ string
  1220.  
  1221.         authorSection ::=       ‘author’ string
  1222.  
  1223.         versionSection ::=      ‘version’ {digit} [‘.’ [digit [digit]]]
  1224.  
  1225.         exportsSection ::=      ‘exports’ exportsList
  1226.  
  1227.         extEntrySection ::=     ‘extEntry’ identifierList
  1228.  
  1229.         objectsSection ::=      ‘objects’ identifierList
  1230.  
  1231.         identifierList ::=      ‘{’ {identifier} ‘}’
  1232.  
  1233.         exportsList ::=         ‘{’ {identifier [‘=’ integer]} ‘}’
  1234.  
  1235.         A string is any collection of characters contained within quotation
  1236.         marks  (either single or double − it doesn’t matter).  If you use a
  1237.         single quote to  start the string, it may contain double quotes and
  1238.         vice versa.  If you want  the string to contain the type of quote
  1239.         that it is delimited by, you must  write two quotes in a row.  If you
  1240.         don’t want to include whitespace  characters in the string, you can
  1241.         leave out the quotes altogether.  This  sounds very complicated, but
  1242.         it’s really quite simple.  Some examples of  valid strings will help:
  1243.  
  1244.                 "This string doesn't contain any errors"
  1245.  
  1246.                 'This string has a "quote"'
  1247.  
  1248.                 '"What''s David doing?" said Sarah.'
  1249.  
  1250.                 unQuotedString
  1251.  
  1252.         An identifier is any series of characters delimited by whitespace. An
  1253.         integer is a sequence of decimal digits − hex integers are not
  1254.         allowed. Comments may be inserted anywhere in the file.  Comments
  1255.         always  begin with a whitespace character (to distinguish them from
  1256.         strange  identifiers).  There are two types of comments:
  1257.  
  1258.         •  Line comments start with any one of ‘;’, ‘|’, ‘//’ or ‘#’ and
  1259.            extend to  the end of the current line.
  1260.  
  1261.         •  Block comments start with ‘/*’ and end with ‘*/’. Whitespace
  1262.            characters include spaces, newlines, tabs and formfeeds.
  1263.  
  1264.         The length of a single line is not limited.  The size of a single
  1265.         token is  limited by the available memory.
  1266.  
  1267.         Null characters (ASCII 0) are not permitted in the definition file.
  1268.  
  1269.  
  1270. Creating definition files
  1271.  
  1272.         Definition files are probably easiest created by using the cdll tool.
  1273.         You  can create a definition file from any collection of object (AOF)
  1274.         and library  (ALF) files by using the command
  1275.  
  1276.                 cdll -def <output file> -o <object file>...
  1277.  
  1278.         This will create a DLL definition file called <output file>
  1279.         containing  declarations of all the external symbols defined by the
  1280.         <object file>s.   The symbols are not output in any particular order
  1281.  
  1282.  
  1283. Definition file sections
  1284.  
  1285.     The name section
  1286.  
  1287.         This section defines the name of the DLL described by the file.  If
  1288.         the file  is not being used to describe a DLL, this section is
  1289.         ignored and may be  omitted.
  1290.  
  1291.         The name may be at most 10 characters long.
  1292.  
  1293.         See the section Registering names for more details about DLL names.
  1294.  
  1295.     The author section
  1296.  
  1297.         This section may contain any string of up to 49 characters, although
  1298.         it is  anticipated that this will be used to contain the author’s
  1299.         copyright notice  or similar string.  It is ignored if the file is
  1300.         not being used to describe a  DLL, and may be omitted under these
  1301.         circumstances.
  1302.  
  1303.     The version section
  1304.  
  1305.         This section defines the version number of the DLL described by the
  1306.         file.   If the file is not being used to describe a DLL, this section
  1307.         is ignored and  may be omitted.
  1308.  
  1309.         The version number contains a major version number, which is any
  1310.         collection of digits, a ‘.’ and between zero and two more digits of
  1311.         minor  version number.
  1312.  
  1313.         It is vitally important that this number is kept up to date, and that
  1314.         it is  increased with every new version released.  Failure to do this
  1315.         can cause  severe problems.
  1316.  
  1317.     The exports section
  1318.  
  1319.         This section declares all the symbols exported by the DLL or
  1320.         application  described by the file.
  1321.  
  1322.         When creating DLL headers or application entry points (see below),
  1323.         this  section defines the symbols whose names are to be placed in the
  1324.         entry  point table.  Entry veneers are also created for each of the
  1325.         symbols  specified.  You should not put symbols which do not need to
  1326.         be exported  to clients in this section − you should use the extEntry
  1327.         section for these  instead.
  1328.  
  1329.         Each name decared in this section may have an ordinal specified with
  1330.         it.   An ordinal is simply an unsigned integer which defines the
  1331.         particular  entry point uniquely within the DLL or application.  Note
  1332.         that the  ordinals should start at 0 and should form a contiguous
  1333.         sequence.  Gaps  in the sequence cause space to be wasted in the
  1334.         entry point table.  Using  ordinals makes application startup faster
  1335.         and uses less memory.   However, you must ensure that the ordinal for
  1336.         each routine stays the  same for all versions of the library.
  1337.  
  1338.         This section is filled in in no particular order by cdll when
  1339.         creating  definition files.  cdll does not automatically assign
  1340.         ordinals to entry point  names.
  1341.  
  1342.     The extEntry section
  1343.  
  1344.         This section declares routines which require veneers to be called
  1345.         externally (e.g. any routine in a DLL which may be called externally
  1346.         through a function pointer).
  1347.  
  1348.         When creating DLL headers (see below), this section defines the
  1349.         symbols  which must have veneers created for them but which should
  1350.         not be  included in the entry point table (i.e. they should not be
  1351.         called directly by  clients).
  1352.  
  1353.         When creating veneers for DLL clients (e.g. module clients), this
  1354.         section  defines the symbols which must have veneers created for them
  1355.         because  they can be called externally.
  1356.  
  1357.     The objects section
  1358.  
  1359.         This section gives the names of the object files (both AOF and ALF)
  1360.         which  contain the symbols declared in the exports and extEntry
  1361.         sections.  This is  so that cdll can check that all of these symbols
  1362.         are valid and defined, in an  attempt to prevent errors.
  1363.  
  1364.  
  1365. Creating DLL headers with cdll
  1366.  
  1367.         DLL headers contain all the information the DLLManager needs to know
  1368.         about a particular DLL.  These can then be linked with the object
  1369.         files  which contain the actual DLL code to create the finished DLL.
  1370.  
  1371.         The command line to create a DLL header from a DLL definition file
  1372.         is:
  1373.  
  1374.                 cdll -def <defn file> -hdr <header file>
  1375.  
  1376.         which creates a DLL header from the DLL definition file <defn file>
  1377.         and  outputs the DLL header in an AOF file called <header file>. The
  1378.         entry veneers for the DLL’s entry points are each given symbols
  1379.         formed by prefixing the name of the routine being veneered with the
  1380.         string ‘_dllEntry_’, so that for example the routine wimpt_init has
  1381.         an  entry veneer called _dllEntry_wimpt_init.  This applies to
  1382.         symbols in  both the exports and extEntry sections.
  1383.  
  1384.  
  1385. Creating DLL stubs with cdll
  1386.  
  1387.         In order to automate the process of initialising a program which uses
  1388.         shared DLLs, it is possible to create tables describing the DLLs
  1389.         required  by the program.  These tables are detected by the
  1390.         replacement Shared C  Library stubs, which proceed to find the
  1391.         required DLLs and fill in branch  tables with branches to entry
  1392.         points within the DLLs.  The tables are  contained in AOF files
  1393.         called DLL stubs which may be linked with the  client’s main code.
  1394.         The DLLs are found while the Shared C Library is  initialising (i.e.
  1395.         before main is called), so that the linking process is entirely
  1396.         transparent.
  1397.  
  1398.         The DLL stubs may be linked in place of an equivalent statically
  1399.         linked  library to produce the same result, or both could be linked,
  1400.         in which case  as many external references as possible would be
  1401.         resolved through the  DLL stubs, with any remaining being resolved by
  1402.         the statically linked  library in the usual way.
  1403.  
  1404.         To create a DLL stubs file, use the command
  1405.  
  1406.                 cdll -def <defn file> -stub <stub file>
  1407.  
  1408.         This creates a DLL stub AOF file called <stub file> for the DLL
  1409.         described  by <defn file>.
  1410.  
  1411. Creating external entry points for clients with cdll
  1412.  
  1413.         If the client requires that the data relocation be set up correctly
  1414.         (e.g. it is a  module task and needs to be able to access its module
  1415.         workspace), any  external calls to the client must be veneered.
  1416.         Veneers may be set up by  using an abbreviated definition file
  1417.         containing only the extEntry and  objects sections.  The command
  1418.  
  1419.                 cdll -def <defn file> -ext <veneer file>
  1420.  
  1421.         then creates an AOF file called <veneer file> which contains the
  1422.         entry  veneers.  These are very small (only 16 bytes each), but they
  1423.         require a  routine in DLLLib for them to work, so remember to link
  1424.         this in. For each symbol name named in the <defn file>, this creates
  1425.         an entry  veneer called _extEntry_name.  We recommend you use the
  1426.         macro  _extEntry defined in dll.h to define these names.
  1427.  
  1428. _____________________________________________________________________________
  1429.  
  1430.  
  1431.                             The DLLManager module
  1432.  
  1433.  
  1434. Overview
  1435.  
  1436.         The DLLManager module offers a simple set of *commands and a
  1437.         selection of SWI calls for handling Dynamic Link Libraries. Notes
  1438.         about the examples
  1439.  
  1440.         All the examples in this sections are written using the syntax of the
  1441.         Acorn  ARM Assembler, rather than that of the standard BASIC
  1442.         assembler.  This  is because programs which use DLLs are more likely
  1443.         to be written using  the ARM Assembler since its output may be linked
  1444.         with programs  written in high-level languages.
  1445.  
  1446.         Most of the examples are given in the form of complete source files
  1447.         except  that definitions of register names and SWI numbers are
  1448.         omitted.   You may use the example code in your own programs if you
  1449.         want to −  that’s what it’s there for.
  1450.  
  1451. SWI calls
  1452.  
  1453.         Some standard conventions should be observed when communicating  with
  1454.         the DLLManager:
  1455.  
  1456.         •  All strings passed to the DLLManager should be 0-terminated.  The
  1457.            addresses of such strings do not have to be word aligned.
  1458.  
  1459.         •  All other pointers passed to the DLLManager must be word-aligned.
  1460.  
  1461.         •  Version numbers are expressed as integers by multiplying by 100
  1462.            (so  version 7.24 would be represented as 724).
  1463.  
  1464.         •  Unless otherwise stated, R0 is always corrupted on exit from a SWI
  1465.            call, and other registers are preserved.
  1466.  
  1467.         •  All the SWIs execute in SVC mode, they run with FIQs enabled and
  1468.            do not alter the IRQ status.  The re-entrancy of the SWI routines
  1469.            is not  defined, and they should not be used from an interrupt
  1470.            routine.
  1471.  
  1472.         Each SWI call (except DLL_Prologue) has a corresponding function in
  1473.         DLLLib which allows the SWI to be used from C.  These are documented
  1474.         with the SWI here, rather than in the section on DLLLib.  All these
  1475.         functions have names beginning with ‘dll_’, followed by the name of
  1476.         the  SWI (without the ‘DLL_’ prefix) with a lower-case first letter.
  1477.         They all  return a pointer to an os_error structure, which either is
  1478.         NULL to indicate  that the SWI was successful, or contains error
  1479.         information returned by  DLLManager.
  1480.  
  1481.  
  1482.                                                         DLL_Find (SWI &4A300)
  1483.  
  1484.         Links an application to a named shared DLL
  1485.  
  1486. From assembler
  1487.  
  1488.         On entry        R0 = pointer to DLL name
  1489.                         R1 = version number required
  1490.  
  1491.         On exit         R0 = DLL handle for the DLL
  1492.  
  1493. From C
  1494.  
  1495.         Prototype       os_error *dll_find(const char *name,
  1496.                                            int version,
  1497.                                            dll *d)
  1498.  
  1499.         Arguments       name = pointer to the DLL name (R0)
  1500.                         version = version number of DLL to load
  1501.                         dll = pointer to DLL handle to set
  1502.  
  1503. Use
  1504.  
  1505.         This SWI loads the specified DLL into memory if necessary, and
  1506.         returns a  handle to it.
  1507.  
  1508.         The name pointed to by R0 (name) must be either a DLL name (up to 10
  1509.         characters long, case-insensitive) or a fully qualified file name (in
  1510.         which  case the leafname is used as the DLL name).
  1511.  
  1512.         Only DLLs whose version number is greater than or equal to that given
  1513.         in  R1 (version) are found.
  1514.  
  1515.         If the DLL is not currently in memory, it is loaded into the RMA in a
  1516.         way  similar to that performed by DLL_Load.  The file loaded is
  1517.         determined by  the name pointed to by R0:
  1518.  
  1519.         •  If R0 points to a leafname only, the file loaded is given by
  1520.            prefixing  the name with ‘DLL:’ (i.e. the variable DLL$Path is
  1521.            searched, as set up  by the DLLs resource.
  1522.  
  1523.         •  If R0 points to a fully qualified path name, it is assumed that
  1524.            this is the  name of the file to load.  Therefore it is essential
  1525.            that the leafname of  the DLL file matches the name specified in
  1526.            its header. Note that after Finding a DLL, you must supply some
  1527.            space for its  instance variables using DLL_InstanceVars.
  1528.  
  1529. Example of use
  1530.  
  1531.         The example below shows the loading of a single DLL named ‘Steel’.
  1532.  
  1533.                         ADR     R0,steelName
  1534.                         LDR     R1,=104
  1535.                         SWI     DLL_Find
  1536.                         STR     R0,steelHnd
  1537.                         ;
  1538.                         ; Carry on with initialisation...
  1539.                         ;
  1540.  
  1541.         steelName       DCB     "Steel",0
  1542.                         ALIGN
  1543.         steelHnd                DCD     0
  1544.  
  1545.  
  1546.  
  1547.                                                DLL_FindFromTable (SWI &4A301)
  1548.  
  1549. Links an application to a number of DLLs
  1550.  
  1551. From assembler
  1552.  
  1553.         On entry        R0 = pointer to start of external DLL block
  1554.                         R1 = pointer to limit (end+1) of external DLL block
  1555.  
  1556.         On exit         –
  1557.  
  1558. From C
  1559.  
  1560.         Prototype       os_error *dll_findFromTable(const dll_table *t,
  1561.                                                     int entries)
  1562.  
  1563.         Arguments       table = a pointer to an array of dll_table entries
  1564.                         entries = the number of entries in this table
  1565.  
  1566. Use
  1567.  
  1568.         Registers your application as wanting to use DLLs, and finds (using
  1569.         DLL_Find) the DLLs specified in the external DLL block.  R0 and R1
  1570.         may  be equal, in which case no attempt to find any DLLs is made. The
  1571.         entries in the table are as follows:
  1572.  
  1573.                 Table 10.1
  1574.  
  1575.         The entry point name table consists of a number of 0-terminated
  1576.         strings  concatenated together.  The table is terminated by a
  1577.         zero-length string.   Each word in the branch table is filled in turn
  1578.         with a branch instruction to  the address of the next named entry
  1579.         point.
  1580.  
  1581.         If the initial value of a word in the branch table is a valid ordinal
  1582.         value  (i.e. it is lower than the number of entry points declared by
  1583.         the DLL), it is  interpreted as such and the entry is resolved
  1584.         without looking up a name.   If the final entry is a valid ordinal,
  1585.         there must be an additional out-of- range value on the end (e.g.
  1586.         &FFFFFFFF).
  1587.  
  1588.         The name table should contain a name for each word in the branch
  1589.         table  which is not an ordinal.
  1590.  
  1591. Example of use
  1592.  
  1593.         The example code is very similar to that used by the DLLLib library
  1594.         to  load in any DLLs specified in cdll-created DLL stubs files.
  1595.  
  1596.                         IMPORT  |DLL$$Data$$Base|
  1597.                         IMPORT  |DLL$$Data$$Limit|
  1598.                         IMPORT  |x$stack_overflow|
  1599.                         IMPORT  giveMemory
  1600.  
  1601.                         AREA    |Example$$Code|,CODE,READONLY
  1602.  
  1603.         ; linkAll
  1604.         ;
  1605.         ; On entry:     --
  1606.         ; On exit:      a1 == 0 for success, or pointer to error block
  1607.  
  1608.                         EXPORT  linkAll
  1609.         linkAll         ROUT
  1610.  
  1611.                         ; --- Standard APCS header ---
  1612.  
  1613.                         MOV     ip,sp
  1614.                         STMFD   sp!,{fp,ip,lr,pc}
  1615.                         CMP     sp,sl
  1616.                         BLLT    |x$stack_overflow|
  1617.                         SUB     fp,ip,#4
  1618.  
  1619.                         ; --- Load DLLs as required ---
  1620.  
  1621.                         LDR     a1,|DLL$$Data$$Base|    ;Find base of the DLL
  1622.  table
  1623.                         LDR     a2,|DLL$$Data$$Limit|   ;Find the end of the
  1624. table
  1625.                         SWI     XDLL_FindFromTable      ;Load the DLLs we wan
  1626. t
  1627.                         LDMVSDB fp,{fp,sp,pc}^          ;If it failed, return
  1628.  error
  1629.  
  1630.                         ; --- Now allocate workspace for them ---
  1631.                         ;
  1632.                         ; We use the giveMemory code shown in the
  1633.                         ; example for SWI DLL_InstanceVars for this
  1634.  
  1635.                         BL      giveMemory              ;Set up DLL instance
  1636. vars
  1637.                         LDMDB   fp,{fp,sp,pc}^          ;Return with that err
  1638. or code
  1639.  
  1640.                         LTORG
  1641.  
  1642.                         END
  1643.  
  1644.  
  1645.  
  1646.                                                         DLL_Load (SWI &4A302)
  1647.  
  1648.         Loads a DLL into an application’s memory (for extendible applications
  1649. )
  1650.  
  1651. From assembler
  1652.  
  1653.         On entry        R0 = pointer to block of memory
  1654.                         R1 = pointer to filename of DLL
  1655.  
  1656.         On exit         –
  1657.  
  1658. From C
  1659.  
  1660.         Prototype       os_error *dll_load(void *buffer,
  1661.                                            const char *name)
  1662.  
  1663.         Arguments       buffer = pointer to a block in which to load the DLL
  1664.                         name = the name of the file containing the DLL
  1665.  
  1666. Use
  1667.  
  1668.         Loads a dynamic link library into a block of memory. This low-level
  1669.         operation is for occasions when you don’t want a DLL to be shared
  1670.         (e.g. if  it contains user-provided extensions to a specific
  1671.         application). The block pointed to by R0 (buffer) needs to be 20
  1672.         bytes larger than the  DLL itself (you should have already found the
  1673.         size of the DLL file using  OS_File).  This call will load, check and
  1674.         relocate the DLL.  Note that you  will need to supply the DLL with
  1675.         its workspace using DLL_Info and  DLL_SetInstanceVars.
  1676.  
  1677.         You can free the space used by the DLL at any time if you don’t want
  1678.         to  use it any more – no data structures are set up by the
  1679.         DLLManager. Note that the DLL loaded may cause other DLLs to be
  1680.         loaded using  DLL_Find, and so, after calling DLL_Load, you should
  1681.         enter a  DLL_InstanceVars loop to allocate instance variables for
  1682.         them.
  1683.  
  1684. Example of use
  1685.  
  1686.         The example below is very similar to the implementation of the
  1687.         _dll_loadExtension function in DLLLib.  It demonstrates how to load
  1688.         an  extension DLL and initialise it properly.
  1689.  
  1690.                         IMPORT  |x$stack_overflow|
  1691.                         IMPORT  malloc
  1692.                         IMPORT  free
  1693.                         IMPORT  giveMemory
  1694.  
  1695.                         AREA    |Example$$Code|,CODE,READONLY
  1696.  
  1697.         ; loadLocal
  1698.         ;
  1699.         ; On entry:     a1 == pointer to name of DLL to load
  1700.         ; On exit:      a1 == DLL handle for DLL, or 0 for failure
  1701.  
  1702.                         EXPORT  loadLocal
  1703.         loadLocal       ROUT
  1704.  
  1705.                         ; --- APCS header ---
  1706.  
  1707.                         MOV     ip,sp
  1708.                         STMFD   sp!,{v1-v3,fp,ip,lr,pc}
  1709.                         SUB     fp,ip,#4
  1710.                         CMP     sp,sl
  1711.                         BLLT    |x$stack_overflow|
  1712.  
  1713.                         ; --- Find the size of the DLL file ---
  1714.  
  1715.                         MOV     v3,a1                   ;Keep the name pointe
  1716. r safe
  1717.                         MOV     a2,a1                   ;Point to the filenam
  1718. e
  1719.                         MOV     a1,#17                  ;Get information on f
  1720. ile
  1721.                         SWI     XOS_File                ;Get the information
  1722.                         BVS     %10loadLocal            ;If it failed, return
  1723.                         CMP     a1,#1                   ;Make sure it found a
  1724.  file
  1725.                         BNE     %10loadLocal            ;If not, make an erro
  1726. r
  1727.  
  1728.                         ; --- Allocate a block for the DLL ---
  1729.  
  1730.                         ADD     a1,v1,#20               ;Allow space for DLLM
  1731. anager
  1732.                         BL      malloc                  ;Allocate the memory
  1733.                         CMP     a1,#0                   ;Was there enough mem
  1734. ory?
  1735.                         BEQ     %10loadLocal            ;No -- return unhappy
  1736.                         MOV     v2,a1                   ;Keep hold of the poi
  1737. nter
  1738.  
  1739.                         ; --- Load the DLL into the block ---
  1740.  
  1741.                         MOV     a2,v3                   ;Point to the filenam
  1742. e
  1743.                         SWI     XDLL_Load               ;Load the DLL and set
  1744.  it up
  1745.                         BVS     %11loadLocal            ;If it failed, tidy u
  1746. p
  1747.  
  1748.                         ; --- Allocate workspace for the DLL ---
  1749.  
  1750.                         MOV     a1,v2                   ;Get the 'DLL handle'
  1751.                         SWI     XDLL_Info               ;Find out about the D
  1752. LL
  1753.                         MOV     a1,v1                   ;Get the workspace si
  1754. ze
  1755.                         BL      malloc                  ;Allocate the memory
  1756.                         CMP     a1,#0                   ;Was there enough?
  1757.                         BEQ     %11loadLocal            ;No -- tidy everythin
  1758. g up
  1759.                         MOV     v1,a1                   ;Look after the point
  1760. er
  1761.                         MOV     a2,a1                   ;Point to this new bl
  1762. ock
  1763.                         MOV     a1,v2                   ;Point to the DLL blo
  1764. ck
  1765.                         SWI     XDLL_SetInstanceVars    ;Attach the workspace
  1766.  
  1767.                         ; --- Allocate space for new DLLs loaded ---
  1768.                         ;
  1769.                         ; Here we use the giveMemory function shown
  1770.                         ; in the example code for DLL_InstanceVars
  1771.  
  1772.                         BL      giveMemory              ;Set up new shared DL
  1773. Ls
  1774.                         CMP     a1,#0                   ;Did that fail?
  1775.                         BNE     %12loadLocal            ;Yes -- tidy everythi
  1776. ng up
  1777.  
  1778.                         ; --- Return the DLL handle to the caller ---
  1779.  
  1780.                         MOV     a1,v2                   ;Point to the DLL blo
  1781. ck
  1782.                         LDMDB   fp,{v1-v3,fp,sp,pc}^    ;Return to the caller
  1783.  
  1784.                         ; --- Free DLL's instance vars ---
  1785.  
  1786.         12loadLocal     MOV     a1,v1                   ;Point to the workspa
  1787. ce
  1788.                         BL      free                    ;Free the block
  1789.                         ; Drop through to free DLL block
  1790.  
  1791.                         ; --- Free DLL block and return to caller ---
  1792.  
  1793.         11loadLocal     MOV     a1,v2                   ;Point to the DLL blo
  1794. ck
  1795.                         BL      free                    ;Free that up nicely
  1796.                         ; Drop through to exit failed
  1797.  
  1798.                         ; --- Return to caller -- we failed ---
  1799.  
  1800.         10loadLocal     MOV     a1,#0                   ;Return a NULL pointe
  1801. r
  1802.                         LDMDB   fp,{v1-v3,fp,sp,pc}^    ;Return to caller
  1803.  
  1804.                         LTORG
  1805.  
  1806.                         END
  1807.  
  1808.  
  1809.  
  1810.                                                         DLL_Lose (SWI &4A303)
  1811.  
  1812. Informs DLLManager that an application no longer needs a shared DLL
  1813.  
  1814. From assembler
  1815.  
  1816.         On entry        R0 = DLL handle of DLL to remove
  1817.  
  1818.         On exit         –
  1819.  
  1820. From C
  1821.  
  1822.         Prototype       os_error *dll_lose(dll d)
  1823.  
  1824.         Arguments       d = DLL handle of DLL to remove
  1825.  
  1826. Use
  1827.  
  1828.         Removes your application from the list of those using the specified
  1829.         DLL.   If your application was the only one using the DLL, then it
  1830.         will be  removed from memory.
  1831.  
  1832. Example of use
  1833.  
  1834.         The example shows how the DLL loaded in the example for DLL_Find
  1835.         might be disposed of later.
  1836.  
  1837.                         ;
  1838.                         ; Finalisation code...
  1839.                         ;
  1840.                         LDR     R0,steelHnd
  1841.                         SWI     DLL_Lose
  1842.                         ;
  1843.                         ; More code...
  1844.                         ;
  1845.  
  1846.                                                     DLL_AppDying (SWI &4A304)
  1847.  
  1848.         Informs the DLLManager that the application is quitting
  1849.  
  1850. From assembler
  1851.  
  1852.         On entry        –
  1853.  
  1854.         On exit         –
  1855.  
  1856. From C
  1857.  
  1858.         Prototype       os_error *dll_appDying(void)
  1859.  
  1860.         Arguments       −
  1861.  
  1862. Use
  1863.  
  1864.         Makes the DLLManager forget about your application, Losing any DLLs
  1865.         it  Found for you etc.
  1866.  
  1867.  
  1868.                                                 DLL_GiveCLibData (SWI &4A305)
  1869.  
  1870.         Informs the DLLManager where the application’s C Library data is
  1871.  
  1872. From assembler
  1873.  
  1874.         On entry        R0 = pointer to start of C Library data
  1875.  
  1876.         On exit         –
  1877.  
  1878. From C
  1879.  
  1880.         Prototype       os_error *dll_giveCLibData(void *data)
  1881.  
  1882.         Arguments       data = pointer to start of C Library data
  1883.  
  1884. Use
  1885.  
  1886.         Declares to the DLLManager the position of the C Library data for
  1887.         this  application.  This information is used by DLL_FindCLibData to
  1888.         locate  exported CLib data from within a DLL.
  1889.  
  1890.         The Shared C Library data area is considered to begin at the address
  1891.         of  __errno.  Thus it is the address of __errno that should be passed
  1892.         in R0.
  1893.  
  1894. Example of use
  1895.  
  1896.         The example code fragment below just sets up the Shared C Library
  1897.         address for the current application.
  1898.  
  1899.                 LDR     R0,=|__errno|
  1900.                 SWI     XDLL_GiveCLibData
  1901.                 ;
  1902.                 ; Continue with initialisation...
  1903.                 ;
  1904.  
  1905.  
  1906.                                                 DLL_FindCLibData (SWI &4A306)
  1907.  
  1908.         Finds the C Library data for the current application
  1909.  
  1910. From assembler
  1911.  
  1912.         On entry        –
  1913.  
  1914.         On exit         R0 = pointer to start of C Library data
  1915.  
  1916. From C
  1917.  
  1918.         Prototype       os_error *dll_findCLibData(void **p)
  1919.  
  1920.         Arguments       p = *p is set up to point to C Library data
  1921.  
  1922. Use
  1923.  
  1924.         Finds the client’s C Library data, as set up with DLL_GiveCLibData.
  1925.         It is  an error to call this SWI without the application having
  1926.         called  DLL_GiveCLibData.
  1927.  
  1928.         The Shared C Library data is considered to begin at the address of
  1929.         __errno, and thus this call actually gives the address of __errno.
  1930.         It is  mainly used by the DLLLib functions _dll_errno, _dll_iob,
  1931.         _dll_ctype  and _dll_hugeval to locate items of the client’s C
  1932.         Library data from within  a DLL.
  1933.  
  1934.  
  1935.                                                 DLL_InstanceVars (SWI &4A307)
  1936.  
  1937.         Sets up workspace for the shared DLLs linked to the current
  1938.         application
  1939.  
  1940. From assembler
  1941.  
  1942.         On entry        R0 = First call:        −
  1943.                              Subsequent calls:  pointer to a block of
  1944.                                                 size given by  previous
  1945.                                                 call, or 0 if not enough
  1946.                                                 memory was available
  1947.                         R4 = First call:        0 for first call
  1948.                              Subsequent calls:  R4 value from previous call
  1949.  
  1950.         On exit         R0 = size of block required for instance variables
  1951.                         R4 = 0 (no more DLLs to allocate for) or value to
  1952.                              pass to  next call
  1953.  
  1954. From C
  1955.  
  1956.         Prototype       os_error *dll_instanceVars(void *buffer,
  1957.                                    int *size,
  1958.                                    int *magic)
  1959.  
  1960.         Arguments       buffer = a pointer to a block of memory whose size is
  1961.                                  size  as returned by the previous call
  1962.                         size = pointer to an integer to fill in with the size
  1963.                                of the next block to allocate
  1964.                         magic = pointer to an integer, initially zero, to
  1965.                                 pass back to  the next call.  magic will be
  1966.                                 reset to 0 to indicate the  end of the loop.
  1967.  
  1968. Use
  1969.  
  1970.         The call should be used in a loop.  Each time the call returns R4
  1971.         non-zero,  R0 bytes of data should be allocated and passed to the
  1972.         next call.  R4 is  used here because it is preserved over calls to
  1973.         APCS routines (e.g. malloc).   See the flowchart in figure 10.1 for
  1974.         the recommended sequence.
  1975.  
  1976.                 Figure 10.1: Flowchart for calling DLL_InstanceVars
  1977.  
  1978.         If you cannot allocate enough memory, you have two choices:
  1979.  
  1980.         •  Abort the loop and report an error
  1981.  
  1982.         •  Pass R0 (buffer) back to DLL_InstanceVars as 0.  DLL_InstanceVars
  1983.            will return an error.
  1984.  
  1985.         Note that this call will only allocate space for instance variables
  1986.         loaded  using DLL_Find.  You have to use DLL_SetInstanceVars for DLLs
  1987.         loaded  by DLL_Load.
  1988.  
  1989. Example of use
  1990.  
  1991.         The example below shows the implementation of the giveMemory function
  1992.         used in the examples for DLL_Load and DLL_FindFromTable.
  1993.  
  1994.                         IMPORT  |x$stack_overflow|
  1995.                         IMPORT  malloc
  1996.  
  1997.                         AREA    |Example$$Code|,CODE,READONLY
  1998.  
  1999.         ; giveMemory
  2000.         ;
  2001.         ; On entry:     --
  2002.         ; On exit:      a1 == 0 for success, or pointer to error
  2003.  
  2004.                         EXPORT  giveMemory
  2005.         giveMemory      ROUT
  2006.  
  2007.                         MOV     ip,sp
  2008.                         STMFD   sp!,{v1,fp,ip,lr,pc}
  2009.                         SUB     fp,ip,#4
  2010.                         CMP     sp,sl
  2011.                         BLLT    |x$stack_overflow|
  2012.  
  2013.                         MOV     v1,#0                   ;R4 starts off as 0
  2014.         00giveMemory    SWI     XDLL_InstanceVars       ;Get another block si
  2015. ze
  2016.                         LDMVSDB fp,{v1,fp,sp,pc}^       ;If it failed, return
  2017.                         CMP     v1,#0                   ;Is that the end now?
  2018.                         MOVEQ   a1,#0                   ;Yes -- exit with no
  2019. error
  2020.                         LDMEQDB fp,{v1,fp,sp,pc}^       ;Return to caller
  2021.                         BL      malloc                  ;Allocate the block
  2022.                         B       %00giveMemory           ;And go round for ano
  2023. ther
  2024.  
  2025.                         LTORG
  2026.  
  2027.                         END
  2028.  
  2029.  
  2030.                                                  DLL_SetInstanceVars (&4A308)
  2031.  
  2032.         Sets up workspace for a non-shared DLL
  2033.  
  2034. From assembler
  2035.  
  2036.         On entry        R0 = DLL handle
  2037.                         R1 = pointer to block for instance variables
  2038.  
  2039.         On exit         –
  2040.  
  2041. From C
  2042.  
  2043.         Prototype       os_error *dll_setInstanceVars(dll d,void *workspace)
  2044.  
  2045.         Arguments       d = the DLL handle
  2046.                         workspace = pointer to block for instance variables
  2047.  
  2048. Use
  2049.  
  2050.         Provides instance variables for a DLL which was loaded using DLL_Load
  2051.         (not DLL_Find or DLL_FindFromTable).  The DLL handle of such a DLL
  2052.         is the block pointer passed to DLL_Load to load it. You should read
  2053.         the required size of the workspace block using  DLL_Info.
  2054.  
  2055. Example of use
  2056.  
  2057.         See DLL_Load for an example of using this SWI.
  2058.  
  2059.  
  2060.                                                      DLL_AppData (SWI &4A309)
  2061.  
  2062.         Informs the DLLManager of the location of the current application’s
  2063.         workspace
  2064.  
  2065. From assembler
  2066.  
  2067.         On entry        R0 = stack limit pointer (R10 under APCS-R)
  2068.  
  2069.         On exit         –
  2070.  
  2071. From C
  2072.  
  2073.         Prototype       os_error *dll_appData(void)
  2074.  
  2075.         Arguments       −
  2076.  
  2077.         dll_appData finds the stack limit pointer automatically.  You do not
  2078.         need  to specify it yourself.
  2079.  
  2080. Use
  2081.  
  2082.         Declares the application’s data relocation to the DLLManager, so that
  2083.         it  may be found using DLL_Prologue with a null DLL handle.  This is
  2084.         required by module tasks which have external entry veneers.
  2085.  
  2086. Example of use
  2087.  
  2088.         This example shows how a typical module might declare its own data
  2089.         pointer.
  2090.  
  2091.                 MOV     al,sl                   ;Pass pointer to stack limit
  2092.                 SWI     DLL_AppData             ;Register with DLLManager
  2093.  
  2094.  
  2095.                                                         DLL_Prologue (&4A30A)
  2096.  
  2097.         Part of the standard DLL entry veneer code
  2098.  
  2099. From assembler
  2100.  
  2101.         On entry        R0 = return address of this routine
  2102.                         R1 = pointer to stack limit structure
  2103.                         R2 = pointer to base of DLL code, or 0
  2104.  
  2105.  
  2106.         On exit         R0 = new return address (pointer into DLLManager
  2107.                              code)
  2108.                         R1 preserved
  2109.                         R2 preserved
  2110.  
  2111. From C
  2112.  
  2113.         Use of this SWI from C is not supported.
  2114.  
  2115. Use
  2116.  
  2117.         Used in the DLL prologue code to patch up accesses to instance
  2118.         variables.   You shouldn’t need to worry about this one too much.  R2
  2119.         is not a DLL  handle, and the relationship between a DLL handle and
  2120.         the DLL’s code  base address is not defined.  This value of R2 is
  2121.         chosen because it allows a  DLL to find a value which identifies
  2122.         itself to DLLManager efficiently. An R2 value of 0 indicates that you
  2123.         want to find the variables for the base  application (usually a
  2124.         module) as registered by DLL_AppData.
  2125.  
  2126. Example of use
  2127.  
  2128.         The example below illustrates how the veneers generated by cdll work.
  2129.  
  2130.                         ; --- Common part of veneers ---
  2131.  
  2132.         |_dll_common|   MOV     R0,lr
  2133.                         MOV     R1,sl
  2134.                         ADR     R2,|_dll_base|
  2135.                         SWI     DLL_Prologue
  2136.                         MOV     lr,R0
  2137.                         LDMFD   sp!,{R0-R2}
  2138.                         MOV     pc,ip
  2139.  
  2140.                         ; --- Example entry point ---
  2141.  
  2142.                         EXPORT  |_dllEntry_foo|
  2143.                         IMPORT  foo
  2144.  
  2145.         |_dllEntry_foo| STMFD   sp!,{R0-R2}
  2146.                         LDR     ip,[pc]
  2147.                         B       |_dll_common|
  2148.                         DCD     foo
  2149.  
  2150.  
  2151.                                                 DLL_ReadStackPtr (SWI &4A30B)
  2152.  
  2153.         Reads the DLL stack pointer to allow for exceptional flow control
  2154.  
  2155. From assembler
  2156.  
  2157.         On entry        −
  2158.  
  2159.         On exit         R0 = a number suitable for passing to DLL_SetStackPtr
  2160.  
  2161. From C
  2162.  
  2163.         Prototype       os_error *dll_readStackPtr(int *sp)
  2164.  
  2165.         Arguments       sp = *sp is set to a value which may be passed to
  2166.                         dll_setStackPtr.
  2167.  
  2168. Use
  2169.  
  2170.         When a call is made through a DLL or application external entry
  2171.         point,  the caller’s workspace pointer is saved on a special stack.
  2172.         During normal  procedure return, this stack is handled transparently
  2173.         by the DLLManager.   However, if control flow is abnormal (e.g. if
  2174.         you use setjmp and longjmp),  the jump target may have the wrong data
  2175.         pointer.
  2176.  
  2177.         By saving the stack pointer immediately before a longjmp target (or
  2178.         similar), and restoring it after a return via longjmp, this problem
  2179.         may be  circumvented.
  2180.  
  2181.         This routine will read a stack pointer in a form which may be later
  2182.         passed  to DLL_SetStackPtr.
  2183.  
  2184. Example of use
  2185.  
  2186.         _dll_setjmp (see the section on DLLLib below) provides a better way
  2187.         of  calling this SWI, and you should see that call for an example of
  2188.         its use.
  2189.  
  2190. DLL_SetStackPtr (&4A30C)
  2191.  
  2192.         Sets the DLL stack pointer on return via exceptional control flow
  2193.  
  2194. From assembler
  2195.  
  2196.         On entry        R0 = a number returned by DLL_ReadStackPtr
  2197.                         R1 = current stack limit value
  2198.  
  2199.         On exit         −
  2200.  
  2201. From C
  2202.  
  2203.         Prototype       os_error *dll_setStackPtr(int sp)
  2204.  
  2205.         Arguments       sp = an integer set up by dll_readStackPtr.
  2206.  
  2207.         dll_setStackPtr finds the current stack limit automatically.  You do
  2208.         not  need to specify it yourself.
  2209.  
  2210. Use
  2211.  
  2212.         This routine will set the DLL workspace stack pointer from a value
  2213.         set up  by an earlier call to DLL_ReadStackPtr (q.v. for more
  2214.         information).  It also  sets up the data relocation correctly for the
  2215.         stack pointer position.  If the  stack is returned to top-level, the
  2216.         relocation is set from the client’s original  relocation (set through
  2217.         DLL_AppData).
  2218.  
  2219. Example of use
  2220.  
  2221.         _dll_longjmped (see the section on DLLLib below) provides a better
  2222.         way of  calling this routine.  See _dll_setjmp for an example of the
  2223.         use of this  routine.
  2224.  
  2225.  
  2226.                                                      DLL_NameApp (SWI &4A30D)
  2227.  
  2228.         Gives a name to the current application
  2229.  
  2230. From assembler
  2231.  
  2232.         On entry        R0 = pointer to application name
  2233.  
  2234.         On exit         –
  2235.  
  2236. From C
  2237.  
  2238.         Prototype       os_error *dll_nameApp(const char *name)
  2239.  
  2240.         Arguments       name = pointer to the application’s name.
  2241.  
  2242. Use
  2243.  
  2244.         Sets up the current application as having the given name.  This name
  2245.         is  used by various DLLManager *commands.
  2246.  
  2247.         The name may be up to 10 characters long, it must not contain spaces
  2248.         or  control characters and it must be unique in a case-insensitive
  2249.         way.
  2250.  
  2251.         For details on the requirements for names, see the chapter
  2252.         Registering  names.
  2253.  
  2254.  
  2255. DLL_Info (SWI &4A30E)
  2256.  
  2257.         Find information about a specified DLL
  2258.  
  2259. From assembler
  2260.  
  2261.         On entry        R0 = DLL handle
  2262.  
  2263.         On exit         R0 preserved
  2264.                         R1 = pointer to DLL’s name
  2265.                         R2 = version number of DLL
  2266.                         R3 = pointer to DLL’s copyright string
  2267.                         R4 = size of DLL’s instance variable requirements
  2268.  
  2269. From C
  2270.  
  2271.         Prototype       os_error *dll_info(dll d,dll_infostr *i)
  2272.  
  2273.         Arguments       d = the handle of the DLL about which to find
  2274.                             information
  2275.                         i = a pointer to an information structure to fill in
  2276.  
  2277.         dll_infostr fields
  2278.                 dll d = the DLL handle passed as d above
  2279.                 char *name = pointer to the DLL’s name
  2280.                 int version = version number of the DLL
  2281.                 char *author = pointer to the DLL’s author string
  2282.                 unsigned instSize = size in bytes of the DLL’s workspace
  2283.  
  2284. Use
  2285.  
  2286.         Gives pieces of information of varying usefulness about the specified
  2287.         DLL.
  2288.  
  2289. Example of use
  2290.  
  2291.         See DLL_Load for an example of using this SWI.
  2292.  
  2293.  
  2294.                                                    DLL_FindEntry (SWI &4A30F)
  2295.  
  2296.         Find a named entry point in a DLL
  2297.  
  2298. From assembler
  2299.  
  2300.         On entry        R0 = DLL handle
  2301.                         R1 = pointer to entry point name
  2302.  
  2303.         On exit         R0 = pointer to entry point in DLL
  2304.  
  2305. From C
  2306.  
  2307.         Prototype       os_error *dll_findEntry(dll d,
  2308.                                                 const char *name,
  2309.                                                 void (**entry)())
  2310.  
  2311.         Arguments       d = the DLL in which to find an entry point
  2312.                         name = pointer to the name of the entry point to find
  2313.                         entry = *entry is set to point to the entry point
  2314.  
  2315.         If the entry point has a non-void return value, you will need to
  2316.         typecast  your entry argument.
  2317.  
  2318. Use
  2319.  
  2320.         Finds a named entry point in a specified DLL.  This is useful if your
  2321.         application uses DLLs to allow user extensions – you could require
  2322.         that  all DLLs used for this purpose export an entry point (say
  2323.         ‘app_main’) and  use this call to find and call it, possibly
  2324.         supplying your own set of entry  points.
  2325.  
  2326.         Entry point names are case-sensitive, in support of case-sensitive
  2327.         languages like C.
  2328.  
  2329. Example of use
  2330.  
  2331.         The example below locates a named entry point and calls it, passing a
  2332.         single integer argument.
  2333.  
  2334.                 AREA    |Example$$Code|,CODE,READONLY
  2335.  
  2336.         ; callEntry
  2337.         ;
  2338.         ; On entry:     a1 == DLL handle containing entry point
  2339.         ;               a2 == name of entry point
  2340.         ;               a3 == parameter to pass to entry in a1
  2341.         ; On exit:      a1 == pointer to an error block if the entry
  2342.         ;                     point could not be found, or value of a1
  2343.         ;                     on return from entry point
  2344.  
  2345.                         EXPORT  callEntry
  2346.         callEntry       ROUT
  2347.  
  2348.                         ; --- Locate the entry point ---
  2349.  
  2350.                         MOV     ip,lr                   ;Look after the link
  2351. register
  2352.                         SWI     XDLL_FindEntry          ;Locate entry point a
  2353. ddress
  2354.                         MOVVS   pc,ip                   ;If it failed, return
  2355.  error
  2356.  
  2357.                         ; --- Call the entry point ---
  2358.  
  2359.                         MOV     lr,ip                   ;Restore return addre
  2360. ss
  2361.                         MOV     a2,a1                   ;Keep entry point add
  2362. ress
  2363.                         MOV     a1,a3                   ;Put argument in a1
  2364.                         MOV     pc,a2                   ;And exit via the ent
  2365. ry point
  2366.  
  2367.                         LTORG
  2368.  
  2369.                         END
  2370.  
  2371.                                                   DLL_SaveHandle (SWI &4A310)
  2372.  
  2373.         Finds the current application’s handle so that it can be restored
  2374.         later
  2375.  
  2376. From assembler
  2377.  
  2378.         On entry        −
  2379.  
  2380.         On exit         R0 = the current application’s handle
  2381.  
  2382. From C
  2383.  
  2384.         Prototype       os_error *dll_saveHandle(int *handle)
  2385.  
  2386.         Arguments       handle = *handle is filled in with the application
  2387.                                  handle
  2388.  
  2389. Use
  2390.  
  2391.         This SWI allows an application to make sure that its handle is
  2392.         preserved  over OS calls which might otherwise corrupt it.  The
  2393.         application handle  must be valid during any calls to DLLManager with
  2394.         the single exception  of DLL_RestoreHandle.
  2395.  
  2396.         The requirement to save the handle may be dropped if an alternative
  2397.         method of identifying applications is used instead.
  2398.  
  2399. Example of use
  2400.  
  2401.         The example below shows how to call an arbitrary *command while
  2402.         ensuring that the application handle is preserved.
  2403.  
  2404.                         IMPORT  |x$stack_overflow|
  2405.                         IMPORT  system
  2406.  
  2407.         ; safeCommand
  2408.         ;
  2409.         ; On entry:     a1 == pointer to command string to call safely
  2410.         ; On exit:      a1 == 0 if all went well, or a system-style
  2411.         ;                     return code otherwise
  2412.  
  2413.                         EXPORT  safeCommand
  2414.         safeCommand     ROUT
  2415.  
  2416.                         ; --- Create a new stack frame ---
  2417.  
  2418.                         MOV     ip,sp
  2419.                         STMFD   sp!,{v1,fp,ip,lr,pc}
  2420.                         SUB     fp,ip,#4
  2421.                         CMP     sp,sl
  2422.                         BLLT    |x$stack_overflow|
  2423.  
  2424.                         ; --- Get my current handle ---
  2425.  
  2426.                         MOV     a2,a1                   ;Look after command s
  2427. tring
  2428.                         SWI     DLL_SaveHandle          ;Get my application h
  2429. andle
  2430.                         MOV     v1,a1                   ;Save that away for a
  2431.  bit
  2432.  
  2433.                         ; --- Perform the command ---
  2434.  
  2435.                         MOV     a1,a2                   ;Restore the command
  2436. pointer
  2437.                         BL      system                  ;Execute the command
  2438.                         MOV     a2,a1                   ;Save the return code
  2439.  away
  2440.  
  2441.                         ; --- Restore my application handle ---
  2442.  
  2443.                         MOV     a1,v1                   ;Get the application
  2444. handle
  2445.                         SWI     DLL_RestoreHandle       ;Restore to previous
  2446. value
  2447.  
  2448.                         ; --- Return to caller ---
  2449.  
  2450.                         MOV     a1,a2                   ;Reinstate system ret
  2451. urn val
  2452.                         LDMDB   fp,{v1,fp,sp,pc}^       ;Return to caller
  2453.  
  2454.                         LTORG
  2455.  
  2456.                         END
  2457.  
  2458.  
  2459.                                                DLL_RestoreHandle (SWI &4A311)
  2460.  
  2461.         Sets the current application’s handle from an earlier saved copy
  2462.  
  2463. From assembler
  2464.  
  2465.         On entry        R0 = the application handle to set
  2466.  
  2467.         On exit         −
  2468.  
  2469. From C
  2470.  
  2471.         Prototype       os_error *dll_restoreHandle(int *handle)
  2472.  
  2473.         Arguments       handle = pointer to an integer set up by
  2474.                                  dll_saveHandle
  2475.  
  2476. Use
  2477.  
  2478.         This SWI allows an application to restore its handle after OS calls
  2479.         which  might have corrupted it.  The application handle must be valid
  2480.         during  any calls to DLLManager with the single exception of
  2481.         DLL_RestoreHandle.
  2482.  
  2483.         The requirement to save the handle may be dropped if an alternative
  2484.         method of identifying applications is used instead.
  2485.  
  2486. Example of use
  2487.  
  2488.         See SWI DLL_SaveHandle for an example of using this SWI.
  2489.  
  2490.  
  2491.                                             DLL_FindInstanceVars (SWI &4A312)
  2492.  
  2493. From assembler
  2494.  
  2495.         On entry        R0 = DLL handle
  2496.  
  2497.         On exit         R0 = pointer to the DLL’s instance variable area
  2498.  
  2499. From C
  2500.  
  2501.         Prototype       os_error *dll_findInstanceVars(dll d,int **addr)
  2502.  
  2503.         Arguments       d = a DLL handle
  2504.                         size = address to store the instance variable area
  2505.                                pointer
  2506.  
  2507. Use
  2508.  
  2509.         Finds the address of an extension DLL’s instance variables.  This
  2510.         saves  you from having to store this address separately so you can
  2511.         free it again  later.
  2512.  
  2513.                                        DLL_RegisterAppEntryTable (SWI &4A313)
  2514.  
  2515. From assembler
  2516.  
  2517.         On entry        R0 = pointer to an entry point address list
  2518.                         R1 = pointer to the entry point name list
  2519.  
  2520.         On exit         −
  2521.  
  2522. From C
  2523.  
  2524.         Prototype       os_error *dll_registerAppEntryTable(void (**btable)()
  2525. ,
  2526.                                                             char *names)
  2527.  
  2528.         Arguments       btable = pointer to address table
  2529.                         names = pointer to entry point name list
  2530.  
  2531. Use
  2532.  
  2533.         Registers an application’s entry point table with the DLLManager, so
  2534.         that  DLLs can call entry points within the client.
  2535.  
  2536.         The name list contains the names of the entry points, in order,
  2537.         separated  by single null bytes.  Dummy entries, for unused entry
  2538.         points, may be  indiciated by a single byte containing the value ‘1’.
  2539.         The whole list is  terminated by a zero length entry.  The address
  2540.         table contains the  addresses of the entry points in order.
  2541.  
  2542.         The entry point table contains four byte addresses of the actual
  2543.         routines.   Ordinals are simply indices into this table.
  2544.  
  2545.  
  2546.                                                 DLL_FindAppEntry (SWI &4A314)
  2547.  
  2548. From assembler
  2549.  
  2550.         On entry        R0 = pointer to entry point name
  2551.  
  2552.         On exit         R0 = pointer to entry point address
  2553.  
  2554. From C
  2555.  
  2556.         Prototype       os_error *dll_findAppEntry(char *name,void (**func)()
  2557. )
  2558.  
  2559.         Arguments       name = pointer to entry point name
  2560.                         func = address to store the entry point address
  2561.  
  2562. Use
  2563.  
  2564.         Looks up a named entry point within the currently executing client
  2565.         application.
  2566.  
  2567.  
  2568.                                            DLL_SetExtensionTable (SWI &4A315)
  2569.  
  2570. From assembler
  2571.  
  2572.         On entry        R0 = pointer to branch table to fill in
  2573.                         R1 = pointer to name list
  2574.  
  2575.         On exit         −
  2576.  
  2577. From C
  2578.  
  2579.         Prototype       os_error *dll_setExtensionTable(void (**btable)(),
  2580.                                                         char *names)
  2581.  
  2582.         Arguments       btable = pointer to branch table to fill in
  2583.                         names = pointer to name list
  2584.  
  2585. Use
  2586.  
  2587.         Fills in an area of memory with branch instructions to specified
  2588.         entry  points within the currently executing client application.
  2589.  
  2590.         Each entry in the branch table initially lower than &1000 is
  2591.         considered to  be the ordinal of the entry point to find, thus
  2592.         bypassing the normal name  lookup.  Entries greater than &1000 are
  2593.         filled in by finding the entry point  whose name matches the next
  2594.         entry in the name table.
  2595.  
  2596.         The name list contains entry point names each separated by a single
  2597.         zero  byte, one for each entry in the branch table not interpreted as
  2598.         an ordinal.   The whole list is terminated by a zero-length entry.
  2599.         If the branch table  initially only contains ordinals, it must be
  2600.         terminated by a value greater  than &1000 and the name list contains
  2601.         only a zero byte.
  2602.  
  2603.  
  2604. *Commands
  2605.  
  2606.                                                                         *DLLs
  2607.  
  2608.         Lists the shared DLLs currently in memory
  2609.  
  2610. Syntax
  2611.  
  2612.         *DLLs [<application name>]
  2613.  
  2614. Parameters
  2615.  
  2616.         application name = the name of an application (as shown by *DLLApps)
  2617.  
  2618. Use
  2619.  
  2620.         Shows a list of either all shared DLLs currently loaded if no
  2621.         application name is specified or just those associated with the named
  2622.         application, together with a small quantity of information about
  2623.         each.
  2624.  
  2625.         Application names are not case-sensitive.
  2626.  
  2627. Examples
  2628.  
  2629.         *DLLs           (shows all shared DLLs loaded)
  2630.  
  2631.         *DLLs Glass     (shows the shared DLLs used by the application
  2632.                         ‘Glass’)
  2633.  
  2634.  
  2635.                                                                      *DLLApps
  2636.  
  2637.         Shows the current DLL client applications.
  2638.  
  2639. Syntax
  2640.  
  2641.         *DLLApps [<DLL name>]
  2642.  
  2643. Parameters
  2644.  
  2645.         DLL name = the name of a DLL (as shown by *DLLs)
  2646.  
  2647. Use
  2648.  
  2649.         Lists either the names of all DLL client applications (if no DLL name
  2650.         is specified) or the applications using the named DLL. If you specify
  2651.         a DLL name, the version of the DLL used by each client is also
  2652.         displayed (since multiple versions of a DLL may in memory
  2653.         simultaneously).
  2654.  
  2655.         If a client application has not registered a name with the
  2656.         DLLManager, its name is shown as ‘<Untitled>’.
  2657.  
  2658.         DLL names are not case-sensitive.
  2659.  
  2660. Examples
  2661.  
  2662.         *DLLApps        (shows names of all DLL client apps currently
  2663.                         running)
  2664.  
  2665.         *DLLApps Steel  (shows the names of the current clients of the DLL
  2666.                         called ‘Steel’, together with the versions of Steel
  2667.                         which they are using)
  2668.  
  2669.  
  2670.                                                                      *DLLInfo
  2671.  
  2672.         Shows information about a named DLL
  2673.  
  2674. Syntax
  2675.  
  2676.         *DLLInfo <DLL name>
  2677.  
  2678. Parameters
  2679.  
  2680.         DLL name = the name of a shared DLL (as shown by *DLLs)
  2681.  
  2682. Use
  2683.  
  2684.         Shows a large quantity of information about the latest version of a
  2685.         DLL currently loaded:
  2686.  
  2687.         •  Its name
  2688.  
  2689.         •  Its author/copyright string
  2690.  
  2691.         •  Its version number
  2692.  
  2693.         •  The number of clients it has
  2694.  
  2695.         •  The names of all its entry points (this can be quite a long list)
  2696.  
  2697.         DLL names are not case-sensitive.
  2698.  
  2699. Example
  2700.  
  2701.         *DLLInfo Steel  (shows vast quantities of information about Steel)
  2702.  
  2703.  
  2704.                                                                   *DLLKillApp
  2705.  
  2706.         Informs the DLLManager that an application has quit
  2707.  
  2708. Syntax
  2709.  
  2710.         *DLLKillApp <Application name>
  2711.  
  2712. Parameters
  2713.  
  2714.         Application name = the name of an application (as shown by *DLLApps).
  2715.  
  2716. Use
  2717.  
  2718.         Terminates the named application’s use of the DLLManager.  It
  2719.         performs the same actions as SWI DLL_AppDying, and is mainly useful
  2720.         if an application ended abnormally (so that it failed to call
  2721.         DLL_AppDying properly).
  2722.  
  2723.         You should ensure that the application named is not running − if it
  2724.         is, it will probably crash the machine badly once it regains control.
  2725.  
  2726.         Application names are not case-sensitive.
  2727.  
  2728. Example
  2729.  
  2730.         *DLLKillApp VeryBuggy
  2731.                         (kills ‘VeryBuggy’, because it wasn’t able to close
  2732.                         itself down)
  2733.  
  2734.  
  2735.                                                                     *DLLReset
  2736.  
  2737.         Resets the DLLManager
  2738.  
  2739. Syntax
  2740.  
  2741.         *DLLReset
  2742.  
  2743. Parameters
  2744.  
  2745.         −
  2746.  
  2747. Use
  2748.  
  2749.         Resets the DLLManager module, removing all shared DLLs from memory,
  2750.         and freeing up lots of memory.
  2751.  
  2752.         This is useful in the unlikely event that the DLLManager goes out of
  2753.         control, or if you have lots of applications which haven’t closed
  2754.         them selves down properly.  Note that you can’t just RMReinit the
  2755.         DLLManager because it checks to find out if it it still in use.
  2756.  
  2757.         If there are any applications using shared DLLs, using this command
  2758.         will make them all crash very badly when they regain control.  You
  2759.         have been warned.
  2760.  
  2761. Example
  2762.  
  2763.         *DLLReset       (resets the DLLManager)
  2764.  
  2765.  
  2766.                                                                    *DLLEnsure
  2767.  
  2768.         Finds out if a DLL is available for use
  2769.  
  2770. Syntax
  2771.  
  2772.         *DLLEnsure <DLL name> <version>
  2773.  
  2774. Parameters
  2775.  
  2776.         DLL name = either a normal DLL name (as shown by *DLLs) or a fully
  2777.                    qualified pathname version = a decimal version number
  2778.  
  2779. Use
  2780.  
  2781.         Finds out whether a DLL with the name and version specified is
  2782.         available.  The searching is the same as for the SWI DLL_Find.  In
  2783.         summary:
  2784.  
  2785.         •  If DLL name is a full pathname, a normal DLL name is set as the
  2786.            leafname
  2787.  
  2788.         •  If DLL name is a normal DLL name, a pathname is set up by
  2789.            prefixing DLL name with ‘DLL:’.
  2790.  
  2791.         •  The shared DLLs in memory are searched for the normal DLL name and
  2792.            version specified
  2793.  
  2794.         •  If it wasn’t found there, the file specified by the pathname is
  2795.            opened, and examined to see if it is of a high enough version.
  2796.  
  2797.         If the search was successful, the command stops and control returns.
  2798.         If it failed, and error is returned.
  2799.  
  2800.         This is useful for inserting in !Run files for applications.
  2801.  
  2802. Example
  2803.  
  2804.         *DLLEnsure Steel 0.02
  2805.                         (make sure version 0.02 or higher of DLL Steel is
  2806.                         available)
  2807.  
  2808. _____________________________________________________________________________
  2809.  
  2810.  
  2811.                               The DLLLib library
  2812.  
  2813.  
  2814. Overview
  2815.  
  2816.         The library is split internally into three sections:
  2817.  
  2818.         •  An APCS interface to the DLLManager SWIs
  2819.  
  2820.         •  Support functions provided for DLL clients
  2821.  
  2822.         •  ‘Behind the scenes’ support functions for the use of the DLL stubs
  2823.  
  2824.         All the DLLLib functions and macros are defined in the dll.h header
  2825.         file  (file DLL.h.dll in the distribution archive), which should be
  2826.         made  available to C programs via the C$Path mechanism.   The actual
  2827.         code for DLLLib is held within the file DLLLib.o.DLLLib in the
  2828.         Dynamic Linking System distribution archive.  To link the library in,
  2829.         just  add the filename of the library to the linker or compiler
  2830.         command line.  If  you use Acorn’s Make application, you simply drag
  2831.         the DLLLib file to the  Add icon in the Project dialogue box.
  2832.  
  2833. Important note
  2834.  
  2835.         In order to perform its work, the DLLLib library must export private
  2836.         support functions for the use of the replacement Shared C Library
  2837.         stubs.
  2838.  
  2839.         All DLLLib functions and macros have names beginning with the
  2840.         characters ‘_dll’, ‘_ext’ or ‘dll_’.  In order to allow for new
  2841.         features to be  added to the the library, you should consider all
  2842.         identifiers beginning  with these characters to be reserved, and not
  2843.         try to define them in your  own code.
  2844.  
  2845. Support macros
  2846.  
  2847.         So that an application can easily be written to use either dynamic
  2848.         linking  or static (standard) linking, many of the support function
  2849.         definitions are  only enabled if the macro _DLL is defined before
  2850.         including dll.h. To allow for creating libraries which may be
  2851.         compiled to be either  dynamically or statically linked, the macros
  2852.         _dllEntry and _dll_static  are provided.  _dllEntry(name) will return
  2853.         either the name of entry veneer  corresponding to entry point name or
  2854.         name itself, depending on whether  _DLL is defined.  This can be
  2855.         useful for passing addresses of functions.   e.g.
  2856.  
  2857.         void mylib_init(void)
  2858.         {
  2859.           /*
  2860.            * Some code...
  2861.            */
  2862.           atexit(_dllEntry(mylib__exit));
  2863.         }
  2864.  
  2865.         _dll_static is empty if _DLL is defined, and returns static if it
  2866.         isn’t.  It is  useful for declaring internal functions, to which you
  2867.         pass function  pointers to other functions (e.g. mylib__exit in the
  2868.         example given above).
  2869.  
  2870.         The entry veneers created for these functions need to be able to have
  2871.         the  function’s name exported, so when you are creating a DLL, they
  2872.         must be  externally visible.
  2873.  
  2874.         The macro _extEntry() performs a similar job to _dllEntry() −
  2875.         _extEntry(name) becomes _extEntry_name if _DLL is defined, and name
  2876.         if it  isn’t.
  2877.  
  2878. DLLManager SWI interface
  2879.  
  2880.         All of the interface functions return a pointer to an os_error
  2881.         structure,  which is NULL if the call was successful.  Each call
  2882.         corresponds to a  DLLManager SWI, and is documented with it above.
  2883.  
  2884. Other support functions
  2885.  
  2886.         The call interface to these functions is defined in terms of C, since
  2887.         they all  conform to APCS-R.
  2888.  
  2889.         If calling from assembler, load the arguments into registers R0
  2890.         onwards in  the same order as they are defined in the C prototype.
  2891.         On exit, R0  contains the return value or is corrupted and R1-R3 and
  2892.         R12 are cor rupted also.
  2893.  
  2894.         The following functions may be replaced by macros, although they are
  2895.         guaranteed not to multiply re-evaluate their arguments.
  2896.  
  2897.                                                                   _dll_setjmp
  2898.  
  2899. Prototype
  2900.  
  2901.         int _dll_setjmp(void)
  2902.  
  2903. Arguments
  2904.  
  2905.         −
  2906.  
  2907. Return value
  2908.  
  2909.         An integer value representing the current DLL stack pointer in an
  2910.         undefined manner.  This value is suitable for passing to
  2911.         _dll_longjmped.
  2912.  
  2913. Use
  2914.  
  2915.         Returns the current state of the DLL stack, so that it may be
  2916.         restored later  via _dll_longjmped.  The format of the return value
  2917.         is unspecified, and  should not be relied upon.
  2918.  
  2919. Example of use
  2920.  
  2921.         See _dll_longjmped below for an example of use.
  2922.  
  2923.  
  2924.                                                                _dll_longjmped
  2925.  
  2926. Prototype
  2927.  
  2928.         void _dll_longjmped(int ptr)
  2929.  
  2930. Arguments
  2931.  
  2932.         ptr = a stack pointer returned by _dll_setjmp.
  2933.  
  2934. Return value
  2935.  
  2936.         −
  2937.  
  2938. Use
  2939.  
  2940.         Restores the DLL stack after an exceptional procedure return (e.g.
  2941.         through longjmp).
  2942.  
  2943. Example
  2944.  
  2945.         int stackptr=_dll_setjmp();     /* Read DLL stack pointer          */
  2946.         jmp_buf j;                      /* Record stack frame info         */
  2947.  
  2948.         /*
  2949.          * Some setting up...
  2950.          */
  2951.  
  2952.         if (!setjmp(j))
  2953.         {
  2954.           /*
  2955.            * Some stuff involving longjmp...
  2956.            */
  2957.         }
  2958.         else
  2959.         {
  2960.           /* --- Someone longjmped here --- */
  2961.  
  2962.           _dll_longjmped(stackptr);     /* Reset DLL stack nicely          */
  2963.  
  2964.           /*
  2965.            * Do anything else to restore the state
  2966.            */
  2967.         }
  2968.  
  2969.  
  2970.                                                                 _dll_appspace
  2971.  
  2972. Prototype
  2973.  
  2974.         void _dll_appspace(void)
  2975.  
  2976. Arguments
  2977.  
  2978.         −
  2979.  
  2980. Return value
  2981.  
  2982.         −
  2983.  
  2984. Use
  2985.  
  2986.         Registers the location of the caller’s static variables with the
  2987.         DLLManager  so that the relocation is set up properly if the client
  2988.         is entered through an  _extEntry-type veneer.
  2989.  
  2990.         This is only of use to applications which are compiled with the -zM
  2991.         compiler option (i.e. module applications), and even then, the DLL
  2992.         stubs  perform this task on initialisation, unless the client’s DLL
  2993.         table is empty.
  2994.  
  2995.         Therefore, you will only need to make this call if:
  2996.  
  2997.         •  You are writing a module application, and
  2998.  
  2999.         •  You are not using any shared DLLs through the normal stub
  3000.            mechanism, and
  3001.  
  3002.         •  You are using DLLs (either shared or nonshared).
  3003.  
  3004.  
  3005.                                                                 _dll_clibdata
  3006.  
  3007. Prototype
  3008.  
  3009.         void  _dll_clibdata(void)
  3010.  
  3011. Arguments
  3012.  
  3013.         −
  3014.  
  3015. Return value
  3016.  
  3017.         −
  3018.  
  3019. Use
  3020.  
  3021.         Registers the location of the client’s copy of the Shared C Library’s
  3022.         instance data with the DLLManager so that any DLLs which require acce
  3023. ss
  3024.         to this data (e.g. if they output to stderr) can find it.
  3025.         This is normally performed automatically by the DLL stubs, unless the
  3026.         client’s DLL table is empty.  You will therefore only need to use thi
  3027. s call if
  3028.         you are using DLLs without the standard DLL stub mechanism.
  3029.  
  3030.  
  3031.                                                                  _dll_setname
  3032.  
  3033. Prototype
  3034.  
  3035.         void _dll_setname(const char *name)
  3036.  
  3037. Arguments
  3038.  
  3039.         name = pointer to the application’s name (null-terminated)
  3040.  
  3041. Return value
  3042.  
  3043.         −
  3044.  
  3045. Use
  3046.  
  3047.         Registers the client’s name with the DLLManager.  This is not essenti
  3048. al,
  3049.         although it is considered to be ‘polite’.
  3050.  
  3051.         For the rules about client application names, see the chapter Registe
  3052. ring
  3053.         names.
  3054.  
  3055. Example of use
  3056.  
  3057.         _dll_setname("Glass");
  3058.  
  3059.  
  3060.                                                                   _dll_system
  3061.                                                                  _dll_ksystem
  3062.                                                                    _dll_oscli
  3063.                                                                _dll_starttask
  3064.  
  3065. Prototypes
  3066.  
  3067.         int _dll_system(const char *command)
  3068.         int _dll_ksystem(const char *command,int chain)
  3069.         os_error *_dll_oscli(const char *command)
  3070.         os_error *_dll_starttask(const char *command)
  3071.  
  3072. Arguments
  3073.  
  3074.         command = pointer to a null-terminated *command.  For _dll_system,
  3075.                   this  may be prefixed with the characters ‘CHAIN:’ or
  3076.                   ‘CALL:’.
  3077.         chain = 0 to keep the application in memory while the command
  3078.                 executes, nonzero to remove the application.
  3079.  
  3080. Return value
  3081.  
  3082.         _dll_system returns the same values as the standard C function
  3083.         system.   _dll_ksystem returns the same values as _kernel_system.
  3084.         _dll_oscli and  _dll_starttask return 0 for success, or a pointer to
  3085.         a RISC OS-style error  structure for failure.
  3086.  
  3087. Use
  3088.  
  3089.         These are all safe ways of calling *commands.  Each one is an
  3090.         interface to  a standard function which calls a *command, but they
  3091.         save the application handle around the call, so they are safe to use
  3092.         from DLL clients.   The relationship is:
  3093.  
  3094.                 Table 11.1
  3095.  
  3096.         Actually, _dll_oscli and _dll_starttask call the SWIs OS_CLI and
  3097.         Wimp_StartTask directly, rather than going through the veneer
  3098.         functions.
  3099.  
  3100.         This is unlikely to make much difference in practice.
  3101.         _dll_loadExtension
  3102.  
  3103. Prototype
  3104.  
  3105.         dll _dll_loadExtension(const char *name)
  3106.  
  3107. Arguments
  3108.  
  3109.         name = pointer to the filename of a DLL file
  3110.  
  3111. Return value
  3112.  
  3113.         A DLL handle for the newly loaded DLL, or a NULL pointer if the load
  3114.         failed for any reason (e.g. ran out of memory).
  3115.  
  3116. Use
  3117.  
  3118.         This call loads and initialises a local (extension) DLL, and returns
  3119.         a  handle to it.  Space for the DLL is allocated using malloc.  The
  3120.         DLL  handle returned may be used just like any other DLL handle. When
  3121.         you are finished with an extension DLL, you can destroy it simply  by
  3122.         freeing the DLL handle.
  3123.  
  3124. Example of use
  3125.  
  3126.         The example function loads a named extension DLL and initialises it
  3127.         by  calling a named function (in this case myext_init − this would be
  3128.         standard for all the DLLs used by an application), passing it the
  3129.         address  of a table of function pointers within the main application.
  3130.  
  3131.         BOOL myapp_loadExtension(char *name,dll *d,widget *w)
  3132.         {
  3133.           widget (*p)(myapp_entryTable *tbl);
  3134.  
  3135.           *d=_dll_loadExtension(name);
  3136.           if (*d)
  3137.           {
  3138.             wimpt_noerr(dll_findEntry(d,"myext_init",(void (**)())&p));
  3139.             *w=p(&myapp__entryTable);
  3140.           }
  3141.           return (d ? TRUE : FALSE);
  3142.         }
  3143.  
  3144.  
  3145.                                                               _dll_giveMemory
  3146.  
  3147. Prototype
  3148.  
  3149.         void _dll_giveMemory(void)
  3150.  
  3151. Arguments
  3152.  
  3153.         −
  3154.  
  3155. Return value
  3156.  
  3157.         −
  3158.  
  3159. Use
  3160.  
  3161.         Allocates workspace for all the shared DLLs being used by the client
  3162.         which have not yet been allocated any.  Workspace is allocated using
  3163.         malloc.  If there is not enough memory, an error is generated, and
  3164.         (in C) a  SIGOSERROR is raised.
  3165.  
  3166.  
  3167.                                                                 _dll_wimpPoll
  3168.                                                             _dll_wimpPollIdle
  3169.  
  3170. On entry
  3171.  
  3172.         R0 = Wimp_Poll event mask and flags
  3173.         R1 = pointer to block to fill with event data
  3174.         R2 = time to return with an idle event (_dll_wimpPollIdle only)
  3175.         R3 = pointer to poll word in the RMA, if bit 22 of R0 is set
  3176.  
  3177. On exit
  3178.  
  3179.         R0 = Wimp_Poll event code, or pointer to error block
  3180.         V set if an error occurred, or clear otherwise
  3181.         Other registers preserved
  3182.  
  3183. Use
  3184.  
  3185.         Provides a ‘safe’ way to call Wimp_Poll and Wimp_PollIdle.  The entry
  3186.         and exit conditions are the same as those for Wimp_Poll and
  3187.         Wimp_PollIdle.  In particular, if bit 24 is set in R0 on entry, the
  3188.         floating  point status and registers F4-F7 are saved (even under
  3189.         RISC OS 2).  This is  of course only performed if the floating point
  3190.         emulator is loaded. These functions are not intended to be used
  3191.         directly from C, but rather  through an OS library’s Wimp interface
  3192.         (where they can be used as a  drop-in replacement for the actual SWIs
  3193.         Wimp_Poll and Wimp_PollIdle).   Indeed, they cannot be used from C,
  3194.         since the V flag requires checking.   Hence it is not declared in the
  3195.         header file.
  3196.  
  3197.  
  3198.                                                                      _dll_iob
  3199.                                                                    _dll_errno
  3200.                                                                    _dll_ctype
  3201.                                                                  _dll_hugeval
  3202.  
  3203.         These functions are for internal use only.  They locate items of data
  3204.         within  the client application’s Shared C Library data area.  Do not
  3205.         use them in  your own code, except through the macros defined in the
  3206.         replacement C  Library headers.
  3207.  
  3208.  
  3209.